Docker基础
Docker基础
容器简介
什么是 Linux 容器
Linux容器是与系统其他部分隔离开的一系列进程,从另一个镜像运行,并由该镜像提供支持进程所需的全部文件。
容器提供的镜像包含了应用的所有依赖项,因而在从开发到测试再到生产的整个过程中,它都具有可移植性和一致性。
在开发应用程序的过程中,开发者通常会面临环境配置不一致的问题。开发者自己的笔记本电脑上的开发环境可能与其他开发人员的环境有所差异,同时还需要考虑到企业的标准化测试和生产环境,这些环境都有自己的配置和必须的支持文件。
为了确保应用程序能够在不同的环境中稳定运行,并通过质量检测,同时在部署过程中避免出现问题,减少重新编写代码和修复故障的需求,可以使用容器技术。容器能够包含应用程序运行所需的所有配置和文件,确保应用程序可以在开发、测试和生产的整个流程中无缝运行,从而避免潜在的危机,实现各方满意的结果。这种方式允许开发者在本地模拟标准化的环境,而不需要承担重建服务器环境的成本和劳力。
容器不就是虚拟化吗
是,但也不竟然。我们用一种简单方式来思考一下:
虚拟化使得许多操作系统可同时在单个系统上运行。
容器则可共享同一个操作系统内核,将应用进程与系统其他部分隔离开。
这意味着什么?首先,让多个操作系统在单个虚拟机监控程序上运行以实现虚拟化,并不能达成和使用容器同等的轻量级效果。
事实上,在仅拥有容量有限的有限资源时,您需要能够可以进行密集部署的轻量级应用。
Linux 容器可从单个操作系统运行,在所有容器中共享该操作系统,因此应用和服务能够保持轻量级,并行快速运行。
什么是 Docker
“Docker” 一词指代多种事物,包括开源社区项目、开源项目使用的工具、主导支持此类项目的公司 Docker Inc. 以及该公司官方支持的工具。技术产品和公司使用同一名称,的确让人有点困惑。
Docker 是一个开源的平台,它使用容器技术来使应用程序的部署、运行和管理变得简单、快速。容器可以被视为轻量级、可移植、自给自足的包,它包含了运行应用程序所需的一切:代码、运行时环境、库、环境变量和配置文件。
借助 Docker ,您可将容器当做重量轻、模块化的虚拟机使用。同时,您还将获得高度的灵活性,从而实现对容器的高效创建、部署及复制,并能将其从一个环境顺利迁移至另一个环境。
Docker 如何工作
Docker 技术使用 Linux 内核和内核功能(例如 Cgroups 和 namespaces)来分隔进程,以便各进程相互独立运行。
这种独立性正是采用容器的目的所在;它可以独立运行多种进程、多个应用程序,更加充分地发挥基础设施的作用,同时保持各个独立系统的安全性。
容器工具(包括 Docker)可提供基于镜像的部署模式。这使得它能够轻松跨多种环境,与其依赖程序共享应用或服务组。Docker 还可在这一容器环境中自动部署应用程序(或者合并多种流程,以构建单个应用程序)。
此外,由于这些工具基于 Linux 容器构建,使得 Docker 既易于使用,又别具一格 —— 它可为用户提供前所未有的高度应用程访问权限、快速部署以及版本控制和分发能力。
docker的目标
docker的主要目标是"Build,Ship and Run any App,Angwhere",构建,运输,处处运行
-
构建:做一个docker镜像
-
运输:docker pull
-
运行:启动一个容器
每一个容器,他都有自己的文件系统rootfs.
Docker基础
Docker基础命令操作
查看docker相关信息
docker version
配置docker镜像加速
vi /etc/docker/daemon.json
修改为以下内容
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
启动第一个容器
docker run -d -p 80:80 nginx
参数说明
Docker镜像生命周期
Docker镜像相关操作
搜索官方仓库镜像
docker search centos
列表说明
获取镜像
根据镜像名称拉取镜像
docker pull centos
查看当前主机镜像列表
docker image list
拉第三方镜像方法
docker pull index.tenxcloud.com/tenxcloud/httpd
导出镜像
docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest ff426288ea90 3 weeks ago 207MB
nginx latest 3f8a4339aadd 5 weeks ago 108MB
# 导出
docker image save centos > docker-centos.tar.gz
删除镜像
docker image rm centos:latest
导入镜像
docker image load -i docker-centos.tar.gz
查看镜像的详细信息
docker image inspect centos
容器的日常管理
容器的起/停
最简单的运行一个容器
docker run nginx
创建容器,两步走(不常用)
docker create centos:latest /bin/bash
docker start stupefied_nobel
快速启动容器方法
docker run centos:latest /usr/bin/sleep 20;
容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!
查看正在运行的容器
docker container ls
# 或
docker ps
查看你容器详细信息/ip
docker container inspect 容器名称/id
查看你所有容器(包括未运行的)
docker ps -a
停止容器
docker stop 容器名称/id
# 或
docker container kill 容器名称/id
进入容器方法
启动时进去方法
docker run -it
#参数:-it 可交互终端
docker run -it nginx:latest /bin/bash
退出/离开容器
ctrl+p
# 或
ctrl+q
启动后进入容器的方法
attach进入容器,使用pts/0 ,会让所用通过此方法进如放入用户看到同样的操作。
docker attach 容器名称/id
exec 进入容器方法(推荐使用),会重新分配一个终端。
docker exec -it clsn1 /bin/bash
删除所有容器
docker rm -f `docker ps -a -q`
# -f 强制删除
启动时进行端口映射
-p参数端口映射
docker run -d -p 8888:80 nginx:latest
不同指定映射方法
随机映射 -P
需要镜像支持
Docker 数据卷的管理
挂载时创建卷
挂载卷
docker run -d -p 80:80 -v /data:/usr/share/nginx/html nginx:latest
容器内站点目录: /usr/share/nginx/html
在宿主机写入数据,查看
echo "<h1>test</h1>" >/data/index.html
curl 10.0.0.100:8080
设置共享卷,使用同一个卷启动一个新的容器
docker run -d -p 8080:80 -v /data:/usr/share/nginx/html nginx:latest
curl 10.0.0.100:8080
查看卷列表
docker volume ls
创建卷后挂载
创建一个卷
docker volume create
查看卷路径
docker volume inspect clsn
使用卷启动容器
docker run -d -p 9000:80 -v clsn:/usr/share/nginx/html nginx:latest
# 宿主机测试
echo '<h1>test</h1>' >/var/lib/docker/volumes/clsn/_data/index.html
curl 10.0.0.100:9000blog.nmtui.com
设置卷启动容器
docker run -d -P --volumes-from 券ID nginx:latest
手动将容器保存为镜像
本次是基于docker官方centos 6.8 镜像创建
启动一个centos6.8的镜像
docker pull centos:6.8
docker run -it -p 1022:22 centos:6.8 /bin/bash
# 在容器种安装sshd服务,并修改系统密码
/ # yum install openssh-server -y
/ # echo "root:123456" |chpasswd
/ # /etc/init.d/sshd start
启动完成后镜像ssh连接测试
将容器提交为镜像
docker commit brave_mcclintock centos6-ssh
使用新的镜像启动容器
docker run -d -p 1122:22 centos6-ssh:latest /usr/sbin/sshd -D
在容器安装httpd服务
# yum install httpd -y
编写启动脚本脚本
# cat init.sh
#!/bin/bash
/etc/init.d/httpd start
/usr/sbin/sshd -D
# chmod +x init.sh
# 注意执行权限
再次提交为新的镜像
docker commit 容器ID centos6-httpd
启动镜像,做好端口映射
docker run -d -p 1222:22 -p 80:80 centos6-httpd /init.sh
Dockerfile自动构建docker镜像
官方构建dockerffile文件参考
https://github.com/CentOS/CentOS-Dockerfiles
Dockerfile指令集
dockerfile主要组成部分:
-
基础镜像信息 FROM centos:6.8
-
制作镜像操作指令RUN yum insatll openssh-server -y
-
容器启动时执行指令 CMD ["/bin/bash"]
dockerfile常用指令:
-
FROM 这个镜像的妈妈是谁?(指定基础镜像)
-
MAINTAINER 告诉别人,谁负责养它?(指定维护者信息,可以没有)
-
RUN 你想让它干啥(在命令前面加上RUN即可)
-
ADD 给它点创业资金(COPY文件,会自动解压)
-
WORKDIR 我是cd,今天刚化了妆(设置当前工作目录)
-
VOLUME 给它一个存放行李的地方(设置卷,挂载主机目录)
-
EXPOSE 它要打开的门是啥(指定对外的端口)
-
CMD 奔跑吧,兄弟!(指定容器启动后的要干的事情)
dockerfile其他指令:
-
COPY 复制文件
-
ENV 环境变量
-
ENTRYPOINT 容器启动后执行的命令
创建一个Dockerfile
创建第一个Dockerfile文件
# 创建目录
mkdir /op/base
cd /opt/base
# 创建Dcokerfile文件,注意大小写
vim Dockerfile
# 内容如下
FROM centos:6.8
RUN yum install openssh-server -y
RUN echo "root:123456" |chpasswd
RUN /etc/init.d/sshd start
CMD ["/usr/sbin/sshd","-D"]
构建docker镜像
docker image build -t centos6.8-ssh .
# -t 为镜像标签打标签 . 表示当前路径
使用自构建的镜像启动
docker run -d -p 2022:22 centos6.8-ssh-b
Docker中的镜像分层
参考文档:
http://www.maiziedu.com/wiki/cloud/dockerimage/
Docker 支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。
从上图可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。
Docker 镜像为什么分层
镜像分层最大的一个好处就是共享资源。
比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内。这就是容器 Copy-on-Write 特性。
可写的容器层
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。
容器层的细节说明
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。
文件操作的
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。
使用docker运行zabbix-server
容器间的互联
在运行zabbix之前务必要了解容器间互联的方法
# 创建一个nginx容器
docker run -d -p 80:80 nginx
# 创建容器,做link,并进入容器中
docker run -it --link quirky_brown:web01 centos-ssh /bin/bash
# 在容器中访问nginx容器可以ping通
ping web01
命令执行过程
# 启动apache容器
docker run -d httpd:2.4
docker ps -a
# 拉取一个busybox 镜像
docker pull busybox
# 启动容器
docker run -it --link determined_clarke:web busybox:latest /bin/sh
# 使用新的容器访问最初的web容器
/ # ping web
启动zabbix容器
1、启动一个mysql的容器
docker run --name mysql-server -t \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-d mysql:5.7 \
--character-set-server=utf8 --collation-server=utf8_bin
2、启动java-gateway容器监控java服务
docker run --name zabbix-java-gateway -t \
-d zabbix/zabbix-java-gateway:latest
3、启动zabbix-mysql容器使用link连接mysql与java-gateway。
docker run --name zabbix-server-mysql -t \
-e DB_SERVER_HOST="mysql-server" \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-e ZBX_JAVAGATEWAY="zabbix-java-gateway" \
--link mysql-server:mysql \
--link zabbix-java-gateway:zabbix-java-gateway \
-p 10051:10051 \
-d zabbix/zabbix-server-mysql:latest
4、启动zabbix web显示,使用link连接zabbix-mysql与mysql。
docker run --name zabbix-web-nginx-mysql -t \
-e DB_SERVER_HOST="mysql-server" \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
--link mysql-server:mysql \
--link zabbix-server-mysql:zabbix-server \
-p 80:80 \
-d zabbix/zabbix-web-nginx-mysql:latest
关于zabbix API
关于zabbix API可以参考官方文档:
https://www.zabbix.com/documentation/3.4/zh/manual/api
1、获取token方法
# 获取token
curl -s -X POST -H 'Content-Type:application/json' -d '
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "Admin",
"password": "zabbix"
},
"id": 1
}' http://10.0.0.100/api_jsonrpc.php
{"jsonrpc":"2.0","result":"d3be707f9e866ec5d0d1c242292cbebd","id":1}
docker 仓库(registry)
创建一个普通仓库
1、创建仓库
docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry
2、修改配置文件,使之支持http
cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"],
"insecure-registries": ["10.0.0.100:5000"]
}
# 重启docker让修改生效
systemctl restart docker.service
3、修改镜像标签
docker tag busybox:latest 10.0.0.100:5000/clsn/busybox:1.0
docker images
4、将新打标签的镜像上传镜像到仓库
docker push 10.0.0.100:5000/clsn/busybox
带basic认证的仓库
1、安装加密工具
yum install httpd-tools -y
2、设置认证密码
mkdir /opt/registry-var/auth/ -phtpasswd -Bbn clsn 123456 > /opt/registry-var/auth/htpasswd
3、启动容器,在启动时传入认证参数
docker run -d -p 5000:5000 -v /opt/registry-var/auth/:/auth/ -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry
4、使用验证用户测试
# 登陆用户
docker login 10.0.0.100:5000
# 推送镜像到仓库
docker push 10.0.0.100:5000/clsn/busybox
#认证文件的保存位置
cat .docker/config.json
{
"auths": {
"10.0.0.100:5000": {
"auth": "Y2xzbjoxMjM0NTY="
},
"https://index.docker.io/v1/": {
"auth": "Y2xzbjpIenNAMTk5Ng=="
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/17.12.0-ce (linux)"
}
}
docker-compose编排工具
安装docker-compose
安装docker-compose
# 下载pip软件
yum install -y python2-pip
# 下载 docker-compose
pip install docker-compose
国内开启pip 下载加速:
http://mirrors.aliyun.com/help/pypi
mkdir ~/.pip/
cat > ~/.pip/pip.conf <<'EOF'
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
EOF
编排启动镜像
1、创建文件目录
mkdir /opt/my_wordpress/
cd /opt/my_wordpress/
2、编写编排文件
编排文件 docker-compose.yml
内容如下
version: '3'
services:
db:
image: mysql:5.7
volumes:
- /data/db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- /data/web_data:/var/www/html
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
3、启动
docker-compose up
4、浏览器上访问 http://10.0.0.100:8000
进行wordpress的安装即可
Docker网络类型
Bridge默认docker网络隔离基于网络命名空间,在物理机上创建docker容器时会为每一个docker容器分配网络命名空间,并且把容器IP桥接到物理机的虚拟网桥上。
不为容器配置网络功能
此模式下创建容器是不会为容器配置任何网络参数的,如:容器网卡、IP、通信路由等,全部需要自己去配置。
docker run -it --network none busybox:latest /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
与其他容器共享网络配置(Container)
此模式和host模式很类似,只是此模式创建容器共享的是其他容器的IP和端口而不是物理机,此模式容器自身是不会配置网络和端口,创建此模式容器进去后,你会发现里边的IP是你所指定的那个容器IP并且端口也是共享的,而且其它还是互相隔离的,如进程等。
docker run -it --network container:mywordpress_db_1 busybox:latest /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
105: eth0@if106: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
使用宿主机网络
此模式创建的容器没有自己独立的网络命名空间,是和物理机共享一个Network Namespace,并且共享物理机的所有端口与IP,并且这个模式认为是不安全的。
docker run -it --network host busybox:latest /bin/sh
查看网络列表
docker network list
用PIPEWORK为docker容器配置独立IP
-
官方网站:
-
宿主环境:centos7.2
1、安装pipework
wget https://github.com/jpetazzo/pipework/archive/master.zipunzip master.zip cp pipework-master/pipework /usr/local/bin/chmod +x /usr/local/bin/pipework
2、配置桥接网卡
安装桥接工具
yum install bridge-utils.x86_64 -y
修改网卡配置,实现桥接
# 修改eth0配置,让br0实现桥接
cat /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
BOOTPROTO=static
NAME=eth0
DEVICE=eth0
ONBOOT=yes
BRIDGE=br0
cat /etc/sysconfig/network-scripts/ifcfg-br0
TYPE=Bridge
BOOTPROTO=static
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=10.0.0.100
NETMASK=255.255.255.0
GATEWAY=10.0.0.254
DNS1=223.5.5.5
# 重启网络
/etc/init.d/network restart
3、运行一个容器镜像测试:
pipework br0 $(docker run -d -it -p 6880:80 --name httpd_pw httpd) 10.0.0.220/24@10.0.0.254
在其他主机上测试端口及连通性
curl 10.0.0.220
ping 10.0.0.220 -c 1
4、再运行一个容器,设置网路类型为none:
pipework br0 $(docker run -d -it --net=none --name test httpd:2.4) 10.0.0.221/24@10.0.0.254
进行访问测试
curl 10.0.0.221
5、重启容器后需要再次指定:
pipework br0 testduliip 172.16.146.113/24@172.16.146.1pipework br0 testduliip01 172.16.146.112/24@172.16.146.1
Docker跨主机通信之macvlan
创建网络
docker network create --driver macvlan --subnet 10.1.0.0/24 --gateway 10.1.0.254 -o parent=eth0 macvlan_1
设置网卡为混杂模式
ip link set eth0 promisc on
创建使用macvlan网络容器
docker run -it --network macvlan_1 --ip=10.1.0.222 busybox /b
使用容器的建议
1. 不要以拆分方式进行应用程序发布
2. 不要创建大型镜像
3. 不要在单个容器中运行多个进程
4. 不要再镜像内保存凭证,不要依赖IP地址
5. 以非root用户运行进程
6. 不要使用“最新”标签
7. 不要利用运行中的容器创建镜像
8. 不要使用单层镜像
9. 不要将数据存放在容器内