Docker 是一个开源的应用容器引擎,主要利用 linux 内核 namespace 实现沙盒隔离,用
cgroup 实现资源限制。
Docker 支持三种不同的镜像层次存储的 drivers:
aufs、devicemapper、btrfs ;
Aufs:
AUFS (AnotherUnionFS) 是一种 Union FS, 简单来说就是支持将不同目录挂载到同一个虚
拟 文 件 系 统 下 (unite several directories into a single virtual filesystem) 的 文 件 系 统 。 Aufs
driver 是 docker 最早支持的 driver,但是 aufs 只是 linux 内核的一个补丁集而且不太可以会
被合并加入到 linux 内核中。但是由于 aufs 是唯一一个 storage driver 可以实现容器间共享可
执行及可共享的运行库, 所以当你跑成千上百个拥有相同程序代码或者运行库时时候,aufs
是个相当不错的选择。
Device Mapper:
Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在
该机制下,用户可以很方便的根据自己的需要制定实现存储资源的管理策略 ( 详
见:http://www.ibm.com/developerworks/cn/linux/l-devmapper/index.html) 。
Device mapper driver 会创建一个 100G 的简单文件包含你的镜像和容器。每一个容器被限
制 在 10G 大 小 的 卷 内 。 ( 如 果 想 要 调 整 , 参
考 :http://jpetazzo.github.io/2014/01/29/docker-device-mapper-resize/ 。 中 文 译 文 :
http://zhumeng8337797.blog.163.com/blog/static/100768914201452405120107/ )
你可以在启动 docker daemon 时用参数-s 指定 driver:
docker -d -s devicemapper ;
Btrfs:
Btufs driver 在 docker build 可以很高效。但是跟 devicemapper 一样不支持设备间共享存
储(文档里是 does not share executable memory between devices)。
在 没 有 aufs 支 持 的 linux 发 行 版 本 上 (CentOS,opensuse 等 ) 安 装 docker 可 能 就 使 用 了
devicemapper driver。
docker安装
实验环境:rhel7.3
[root@foundation24 docker]# ls
docker-engine-17.03.1.ce-1.el7.centos.x86_64.rpm docker-engine-selinux-17.03.1.ce-1.el7.centos.noarch.rpm
[root@foundation24 docker]# yum install -y *.rpm
[root@foundation24 docker]# systemctl start docker.service
如果你是7.0的系统会有以下报错
rhel7.0 系统会有以下报错:
docker:
/usr/bin/docker:
relocation
error:
/usr/bin/docker:
symbol
dm_task_get_info_with_deferred_remove, version Base not defined in file libdevmapper.so.1.02
with link time reference
需要升级以下几个几个软件包的版本以及内核:
device-mapper-libs-1.02.93-3.el7.x86_64
device-mapper-event-libs-1.02.93-3.el7.x86_64
device-mapper-event-1.02.93-3.el7.x86_64
device-mapper-1.02.93-3.el7.x86_64
kernel-3.10.0-229.el7.x86_64
原理图(来源于网络):
容器管理
# docker run -it --name vm1 ubuntu bash
# docker ps -a
# docker attach vm1
# docker top vm1
查看容器进程
创建容器
查看容器状态
连接容器
# docker logs vm1 查看容器指令输出 -f 参数可以实时查看
# docker inspect vm1 查看容器详情
# docker stats vm1 查看容器资源使用率
# docker diff vm1 查看容器修改# docker run -d --name vm1 ubuntu bash -c "while true; do echo westos; sleep 1; done"
行
# docker stop vm1 停止容器
# docker start vm1 启动容器
# docker kill vm1 强制干掉容器
# docker restart vm1 重启容器
# docker pause/unpause vm1
# docker rm vm1
暂停/恢复容器
删除容器
# docker export vm1 > vm1.tar
# docker import vm1.tar image
导出容器
导入容器为镜像 image
镜像管理
镜像用来创建容器,是容器的只读模板,默认可以从 docker hub 上下载。docker 的镜像是
增量修改,每次创建新的镜像都会在父镜像上构建一个增量的层,基于 AUFS 技术。
# docker search
# docker pull
# docker push
查询镜像
拉取镜像
推送镜像
1.镜像容器的小实验
[root@foundation24 docker]# docker load < game2048.tar ##导入镜像
或者 docker load -i game22048.tar
011b303988d2: Loading layer [==================================================>] 5.05 MB/5.05 MB
36e9226e74f8: Loading layer [==================================================>] 51.46 MB/51.46 MB
192e9fad2abc: Loading layer [==================================================>] 3.584 kB/3.584 kB
6d7504772167: Loading layer [==================================================>] 4.608 kB/4.608 kB
88fca8ae768a: Loading layer [==================================================>] 629.8 kB/629.8 kB
Loaded image: game2048:latest
查看镜像(docker images 看以查看所有拥有的镜像):
[root@foundation24 docker]# docker images game2048 ##查看包
REPOSITORY TAG IMAGE ID CREATED SIZE
game2048 latest 19299002fdbe 20 months ago 55.5 MB
创建容器:
[root@foundation24 docker]# docker run -d --name vm1 game2048 ##创建一个名字叫vm1 的基于game2048镜像的容器,并打入后台
f168c1b2e18bd15e7e543dddadf4280befc53d9d1aeec85a30df0cc6751d09fe
查看正在运行的容器信息
[root@foundation24 docker]# docker ps ##查看正在运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f168c1b2e18b game2048 "/bin/sh -c 'sed -..." 2 minutes ago Up 2 minutes 80/tcp, 443/tcp vm1
查看所有容器信息
[root@foundation24 docker]# docker ps -a ##可以查看正在运行和没有运行的容器,由于我只创建了一个容器,所以只有一个
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f168c1b2e18b game2048 "/bin/sh -c 'sed -..." 2 minutes ago Up 2 minutes 80/tcp, 443/tcp vm1
查看容器的私有段地址:
容器的地址只能本机看到,或者可以将端口映射出来,才会被别的发现。
[root@foundation24 docker]# docker inspect vm1 ##查看信息(获取内部私有段地址)
在浏览器查看容器:
输入私有段IP
2.镜像加速器的安装
镜像默认可以从 docker hub 上下载,这是 docker 官方的公共仓库,为我们免费提供了大量
已经容器化的应用镜像,避免我们重复的去造轮子。但是官方并没有在国内部署服务器,
如果你不走 vpn 的话真的是太慢了,报错和超时让人非常的郁闷。
可以注册一个镜像加速器来使用,我使用的是阿里云的镜像加速器。
点击由上角的控制台:
产品与服务打开之后,右边就有一个容器镜像服务
每个人都会有一个编号
物理机添加镜像加速器配置文件
[root@foundation24 ~]# mkdir -p /etc/docker/
[root@foundation24 ~]# cd /etc/docker/
[root@foundation24 docker]# ls
[root@foundation24 docker]# vim demon.json
[root@foundation24 docker]# systemctl daemon-reload
[root@foundation24 docker]# systemctl restart docker.service
[root@foundation24 docker]# ls
demon.json key.json
测试:
[root@foundation24 docker]# docker search nginx ###查询nginx镜像的所有信息
[root@foundation24 docker]# docker rmi nginx ##镜像删除
[root@foundation24 docker]# docker images nginx ##查看nginx镜像是否存在
REPOSITORY TAG IMAGE ID CREATED SIZE
官网拉取镜像
[root@foundation24 docker]# docker pull nginx ##联网下载nginx镜像
Using default tag: latest
latest: Pulling from library/nginx
be8881be8156: Pull complete
32d9726baeef: Pull complete
87e5e6f71297: Pull complete
Digest: sha256:d85914d547a6c92faa39ce7058bd7529baacab7e0cd4255442b04577c4d1f424
Status: Downloaded newer image for nginx:latest
[root@foundation24 docker]# docker save nginx > nginx.tar ##将拉取镜像保存到nginx.tar中
[root@foundation24 docker]# docker load < nginx.tar ##导入镜像
Loaded image: nginx:latest
[root@foundation24 docker]# docker images nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest c82521676580 3 weeks ago 109 MB
[root@foundation24 docker]# docker run -d --name vm2 nginx
901a5e9e80246e27fee69ce7c8345a2aeb97aa2b3febe34e4f40bf3841424607
[root@foundation24 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
901a5e9e8024 nginx "nginx -g 'daemon ..." 28 seconds ago Up 26 seconds 80/tcp vm2
[root@foundation24 docker]# docker inspect vm2
浏览器查看:
3.数据卷管理
docker run 在创建容器时使用 -v 参数可以挂载一个或多个数据卷到当前运行的容器中,-v的作用是将宿主机上的目录作为容器的数据卷挂载到容器中,使宿主机和容器之间可以共享一个目录。
[root@foundation24 docker]# cd /tmp/docker/web/
[root@foundation24 web]# ls
index.html
[root@foundation24 web]# vim index.html
挂载数据卷到新创建的容器上:
-v 参数可以重复使用,挂载多个数据卷到容器中,冒号前面的是宿主机的目录(本地目录
不存在 docker 会自动创建),冒号后面的是容器中的挂载目录。
[root@foundation24 web]# docker run -d --name vm2 -v /tmp/docker/web/:/usr/share/nginx/html nginx
2af78d7a7983094e19928072a3f20f6eb9ba8862295f0f4a9909d53eacf2425f
默认挂载可以读写数据卷,也可以只读挂载:
[root@foundation24 web]# docker run -it --name vm1 -v /tmp/data1:/data1 -v /tmp/data2:/data2:ro rhel7 bash ##data1可写,data2只读
bash-4.2# cd /data1/
bash-4.2# ls
file1
bash-4.2# touch file1
bash-4.2# ls
file1
bash-4.2# cd /data2/
bash-4.2# touch file
touch: cannot touch 'file': Read-only file system
物理机查看:
[root@foundation24 tmp]# cd data1/
[root@foundation24 data1]# ls
file1
创建数据卷:
[root@foundation24 web]# docker create --name datavol -v /tmp/data1:/data1 -v /tmp/data2:/data2:ro rhel7 bash ##建立卷组
[root@foundation24 web]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
02cbefa8eacc rhel7 "bash" About a minute ago Created datavol
root@foundation24 web]# docker run -it --name vm1 --volumes-from datavol rhel7 bash ##调用逻辑卷组
bash-4.2# ls
bin data1 dev home lib64 mnt proc run srv tmp var
boot data2 etc lib media opt root sbin sys usr
bash-4.2# cd /data1/
bash-4.2# ls
file1
bash-4.2# touch file2
bash-4.2# ls
file1 file2
[root@foundation24 data1]# ls
file1 file2
4,端口映射
[root@foundation24 netns]# docker run -d --name vm1 -p 8080:80 nginx
7c41f7c10454946c63340449f87ef412b3ba062615d4d124bd381a031d381406
[root@foundation24 netns]# iptables -t nat -nL ##Docker 的端口映射是由 iptables 来实现的
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80
5.容器间的互联
–link 参数可以在不映射端口的前提下为两个容器间建立安全连接, –link 参数可以连接一个或多个容器到将要创建的容器。
–link 参数的格式为 –link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。
[root@foundation24 netns]# docker run -it --name vm2 --link vm1:nginx ubuntu ##创建一个vm2容器跟vm1相连,起名字叫nginx 用ubuntu镜像
root@1059f83328d0:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 nginx 7c41f7c10454 vm1
172.17.0.3 1059f83328d0
root@1059f83328d0:/# ping nginx
PING nginx (172.17.0.2) 56(84) bytes of data.
64 bytes from nginx (172.17.0.2): icmp_seq=1 ttl=64 time=0.097 ms
64 bytes from nginx (172.17.0.2): icmp_seq=2 ttl=64 time=0.106 ms
64 bytes from nginx (172.17.0.2): icmp_seq=3 ttl=64 time=0.123 ms
^C
--- nginx ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.097/0.108/0.123/0.016 ms
6.镜像的封装
- 指定容器运行的用户该用户将作为后续的 RUN 命令执行的用户。这个命令本实验不需要,但在一些需要指定用户来运行的应用部署时非常关键,比如提供 hadoop 服务的容器通常会使用 hadoop 用户来启动服务。命令使用方式,例如使用 shiyanlou 用户来执行后续命令:USER shiyanlou
- 指定后续命令的执行目录
由于我们需要运行的是一个静态网站,将启动后的工作目录切换到/var/www/html 录:WORKDIR /var/www/html- 对外连接端口号
由于内部服务会启动 Web 服务,我们需要把对应的 80 端口暴露出来,可以提供给容间互联使用,可以使用 EXPOSE 命令。在镜像操作部分增加下面一句:EXPOSE 80- 设置容器主机名
ENV 命令能够对容器内的环境变量进行设置:
ENV HOSTNAME sevrer1.example.com- 向镜像中增加文件
向镜像中添加文件有两种命令:COPY 和 ADD。
COPY 命令可以复制本地文件夹到镜像中:
COPY website /var/www/html
ADD 命令支持添加本地的 tar 压缩包到容器中指定目录,压缩包会被自动解压为目录,也
可以自动下载 URL 并拷贝到镜像,例如:
ADD html.tar /var/www
ADD http://www.westos.org/html.tar /var/www
根据实验需求,我们把需要的一个网站放到镜像里,需要把一个 tar 包添加到 apache 的
/var/www 目录下,因此选择使用 ADD 命令:
ADD html.tar /var/www- CMD 与 ENTRYPOINT
ENTRYPOINT 容器启动后执行的命令,让容器执行表现的像一个可执行程序一样,与
CMD 的 区 别 是 不 可 以 被 docker run 覆 盖 , 会 把 docker run 后 面 的 参 数 当 作 传 递 给
ENTRYPOINT 指令的参数。Dockerfile 中只能指定一个 ENTRYPOINT,如果指定了很多,
只 有 最 后 一 个 有 效 。 docker run 命 令 的 -entrypoint 参 数 可 以 把 指 定 的 参 数 继 续 传 递 给
ENTRYPOINT。在本实验中两种方式都可以选择。- 挂载数据卷
将 apache 访问的日志数据存储到宿主机可以访问的数据卷中:
VOLUME [“/var/log/apche2”]- 设置容器内的环境变量
使用 ENV 设置一些 apache 启动的环境变量:
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apche2
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOCK_DIR /var/lock/apche2- 使用 Supervisord
CMD 如果只有一个命令,那如果我们需要运行多个服务怎么办呢?最好的办法是分别在不
同的容器中运行,通过 link 进行连接,比如先前实验中用到的 web,app,db 容器。如果一
定要在一个容器中运行多个服务可以考虑用 Supervisord 来进行进程管理,方式就是将多个
启动命令放入到一个启动脚本中。
首先安装 Supervisord,添加下面内容到 Dockerfile:
RUN apt-get install -yqq supervisor
RUN mkdir -p /var/log/supervisor
拷贝配置文件到指定的目录:
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
6.1封装httpd到rhel7中生成一个新的镜像
[root@foundation24 web]# pwd
/tmp/docker/web
[root@foundation24 web]# ls
Dockerfile dvd.repo index.html
[root@foundation24 web]# cat dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.24.250/rhel7.3
gpgcheck=0
[root@foundation24 web]# cat Dockerfile
FROM rhel7
ENV HSTNAME server1
MAINTAINER xiaoqin@westos.org
EXPOSE 80
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd && yum clean all
VOLUME ["/var/www/html"]
CMD ["/usr/sbin/httpd","-D", "FOREGROUND"]
封装httpd镜像
[root@foundation24 web]# docker build -t rhel7:v1 . ##封装一个名叫rhel7:v1的镜像
Successfully built 3697e2f51872
[root@foundation24 web]# docker images rhel7 ##查看镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel7 v1 3697e2f51872 14 minutes ago 169 MB
rhel7 latest 0a3eb3fde7fd 4 years ago 140 MB
[root@foundation24 web]# docker run -d --name vm3 -v /tmp/docker/web/:/var/www/html rhel7:v1
2bf346cf36288511b4c47122340d3d215d92be22075d8756f8a8dc34ae99422b
6.2封装ssh
[root@foundation24 ssh]# pwd
/tmp/docker/ssh
[root@foundation24 ssh]# cat dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.24.250/rhel7.3
gpgcheck=0
[root@foundation24 ssh]# cat Dockerfile
FROM rhel7
ENV HSTNAME server2
MAINTAINER xiaoqin@westos.org
EXPOSE 22
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y openssh-server openssh-clients && yum clean all && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos |chpasswd
CMD ["/usr/sbin/sshd","-D"]
创建镜像
[root@foundation24 ssh]# docker build -t rhel7:v2 .
创建容器
[root@foundation24 ssh]# docker run -d --name vm4 rhel7:v2
105b9869e188fd61c56f577664ffde1d8fe6ef4cf5bae059463a1f48438b050
[root@foundation24 ssh]# docker inspect vm4 ##查看内网ip
连接
[root@foundation24 ssh]# ssh root@172.17.0.5
The authenticity of host '172.17.0.5 (172.17.0.5)' can't be established.
ECDSA key fingerprint is 70:56:84:b8:c2:ce:30:bf:f6:82:70:c0:a2:2a:d2:fb.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.17.0.5' (ECDSA) to the list of known hosts.
root@172.17.0.5's password:
-bash-4.2#
6.3封装镜像的整合:(ssh+httpd)
[root@foundation24 ~]# cd /tmp/docker/
[root@foundation24 docker]# ls
ssh web
[root@foundation24 docker]# mkdir ssh+web
[root@foundation24 docker]# cd ssh+web/
[root@foundation24 ssh+web]# ls
Dockerfile dvd.repo supervisord.conf
[root@foundation24 ssh+web]# cat dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.254.250/rhel7.3
gpgcheck=0
[docker]
name=docker
baseurl=http://172.25.254.250/pub/docker
Gpgcheck=0
[root@foundation24 ssh+web]# vim Dockerfile
[root@foundation24 ssh+web]# cat Dockerfile
FROM rhel7
EXPOSE 80 22
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd openssh-server openssh-clients supervisor && yum clean all && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos |chpasswd
COPY supervisord.conf /etc/supervisord.conf
CMD ["/usr/bin/supervisord”]
[root@foundation24 ssh+web]# cat supervisord.conf
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:httpd]
command=/usr/sbin/httpd
封装镜像
[root@foundation24 ssh+web]# docker build -t rhel7:v3 . ##封装镜像
查看镜像
root@foundation24 ssh+web]# docker images rhel7
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel7 v3 298ed66644c3 About a minute ago 178 MB
rhel7 v2 68cd2199384f 40 hours ago 154 MB
rhel7 v1 e48995d830c1 40 hours ago 169 MB
rhel7 latest 0a3eb3fde7fd 4 years ago 140 MB
创建容器:
[root@foundation24 ssh+web]# docker run -d --name vm1 -v /tmp/docker/web/:/var/www/html rhel7:v3
54fd91a006056b6795a63334a7d3ac126ddfb8985e03a305a2e7e8d31ab1cd1f
测试:
[root@foundation24 ssh+web]# curl 172.17.0.2
<h1>www.westos.org</h1>
<h1>www.westos.org</h1>
[root@foundation24 ssh+web]# ssh -l root 172.17.0.2
The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
ECDSA key fingerprint is 2e:a3:cd:fb:2d:eb:02:48:2f:5d:71:fc:89:12:f2:ee.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
root@172.17.0.2's password:
-bash-4.2#
6.4CMD和ENTRYPOINT的演示
CMD 只能用一次,而且会被覆盖 ,启动 容器的时候才会被调用
ENTRYPOINT 不会被覆盖 ,启动容器的时候才会调用
CMD:
[root@foundation24 docker]# cat Dockerfile
FROM rhel7
CMD echo "hello world"
[root@foundation24 docker]# docker build -t rhel7:v4 .
[root@foundation24 docker]# docker run --rm rhel7:v4
hello world
[root@foundation24 docker]# docker run --rm rhel7:v4 echo westos
westos
ENTRYPOINT:
[root@foundation24 docker]# vim Dockerfile
[root@foundation24 docker]# docker build -t rhel7:v4 .
[root@foundation24 docker]# docker run --rm rhel7:v4
hello world
[root@foundation24 docker]# docker run --rm rhel7:v4 echo westos
hello world
CMD+ENTRYPOINT:
[root@foundation24 docker]# vim Dockerfile
FROM rhel7
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
[root@foundation24 docker]# docker build -t rhel7:v4 .
[root@foundation24 docker]# docker run --rm rhel7:v4
hello world
[root@foundation24 docker]# docker run --rm rhel7:v4 echo westos
hello echo westos
[root@foundation24 docker]# docker run --rm rhel7:v4 westos
hello westos