docker CE on Linux示例浅析(三)镜像与容器管理

原创
2019/05/05 23:29
阅读数 1.5K

概述

github项目地址:https://github.com/superwujc

尊重原创,欢迎转载,注明出处:https://my.oschina.net/superwjc/blog/3045629

历史系列:

docker CE on Linux示例浅析(一)安装与基本运行

docker CE on Linux示例浅析(二)数据存储与持久化

    镜像是静态存储的磁盘文件,容器是动态运行的内存进程,二者可以视为docker一体的两面。在docker的整个工作流程中,与镜像与容器相关的操作贯穿始终,其他功能大都以此为基础进行展开或封装。本文将以jdk + tomcat为例,简述镜像/容器的基本管理,包括构建与运行,以及迁移与恢复过程。

环境

  • 宿主机2台:dock_host_0(192.168.9.168/24),dock_host_1(192.168.9.169/24),均为全新最小化安装,二者的系统与软件环境一致。操作系统版本CentOS Linux release 7.6.1810 (Core),内核版本3.10.0-957.12.1.el7.x86_64,docker为默认安装,版本18.09.5,无其他设置。
  • 源码包jdk-8u212-linux-x64.tar.gz与apache-tomcat-8.5.40.tar.gz,位于宿主机的/opt/目录。
  • 容器所用镜像为最新版CentOS 7官方镜像。
  • jdk环境以命名卷jdks的方式挂载至容器的/opt/jdks目录,以减小镜像占用的磁盘空间,并加快镜像构建的速度。
  • tomcat环境位于容器的/opt/apps/app_0目录,所有设置均为默认。

示例

    获取操作系统镜像centos,并设置命名卷jdks:

[root@docker_host_0 ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}'
192.168.9.168/24
[root@docker_host_0 ~]# docker -v
Docker version 18.09.5, build e8ff056
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
8ba884070f61: Pull complete
Digest: sha256:8d487d68857f5bc9595793279b33d082b03713341ddec91054382641d14db861
Status: Downloaded newer image for centos:latest
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# cd /opt/
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# ll
total 199908
-rw-r--r-- 1 root root   9690027 May  5 21:55 apache-tomcat-8.5.40.tar.gz
drwx--x--x 4 root root        28 May  5 22:04 containerd
-rw-r--r-- 1 root root 195013152 May  5 21:55 jdk-8u212-linux-x64.tar.gz
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker volume create jdks
jdks
[root@docker_host_0 opt]# docker volume ls
DRIVER              VOLUME NAME
local               jdks
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# tar axf jdk-8u212-linux-x64.tar.gz -C /var/lib/docker/volumes/jdks/_data/
[root@docker_host_0 opt]# ll /var/lib/docker/volumes/jdks/_data/
total 0
drwxr-xr-x 7 10 143 245 Apr  2 04:49 jdk1.8.0_212
[root@docker_host_0 opt]#
[root@docker_host_1 ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}'
192.168.9.169/24
[root@docker_host_1 ~]# docker -v
Docker version 18.09.5, build e8ff056
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
8ba884070f61: Pull complete
Digest: sha256:8d487d68857f5bc9595793279b33d082b03713341ddec91054382641d14db861
Status: Downloaded newer image for centos:latest
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# cd /opt/
[root@docker_host_1 opt]# ll
total 199908
-rw-r--r-- 1 root root   9690027 May  5 21:55 apache-tomcat-8.5.40.tar.gz
drwx--x--x 4 root root        28 May  5 21:58 containerd
-rw-r--r-- 1 root root 195013152 May  5 21:55 jdk-8u212-linux-x64.tar.gz
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker volume create jdks
jdks
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker volume ls
DRIVER              VOLUME NAME
local               jdks
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# tar axf jdk-8u212-linux-x64.tar.gz -C /var/lib/docker/volumes/jdks/_data/
[root@docker_host_1 opt]# ll /var/lib/docker/volumes/jdks/_data/
total 0
drwxr-xr-x 7 10 143 245 Apr  2 04:49 jdk1.8.0_212
[root@docker_host_1 opt]#

3.1 构建

    docker镜像的构建过程为逐层进行,上层镜像称为父(parent)镜像,顶层镜像称为基础(base)镜像,通常为操作系统。对于运行中的容器,其可写层中产生的内容变更经过保存(commit),与父镜像共同组成当前层级的镜像。

    镜像的构建可以通过手动与自动的方式。手动方式为重复运行父镜像,将需要定制的内容逐步添加到可写层并保存;自动方式则将需要实现的功能写入到文件(Dockerfile),由docker主进程读取该文件,并按指令完成构建。

3.1.1 手动构建

    以名称t_c_0运行centos镜像,并在容器中创建/opt/apps目录:

[root@docker_host_0 opt]# docker run --name t_c_0 centos bash -c "mkdir -p /opt/apps"
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
6a6a3ed5a380        centos              "bash -c 'mkdir -p /…"   8 seconds ago       Exited (0) 7 seconds ago                       t_c_0
[root@docker_host_0 opt]#

    将tomcat复制到容器的/opt/apps/app_0目录:

[root@docker_host_0 opt]# tar axf apache-tomcat-8.5.40.tar.gz
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# ll -d apache-tomcat-8.5.40
drwxr-xr-x 9 root root 220 May  5 22:15 apache-tomcat-8.5.40
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker cp apache-tomcat-8.5.40 t_c_0:/opt/apps/app_0
[root@docker_host_0 opt]#

    将t_c_0容器的当前状态保存为t_i_0镜像:

[root@docker_host_0 opt]# docker container commit t_c_0 t_i_0
sha256:1aa86a5d25c2933cbf1b5e455435b44b3eb3c5501190116d02c6028cda11a318
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
t_i_0               latest              1aa86a5d25c2        5 seconds ago       216MB
centos              latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_0 opt]#

    以名称t_c_1运行t_i_0镜像,并指定容器的开放端口(--expose),环境变量(-e/--env),工作目录(-w/--workdir):

[root@docker_host_0 opt]# docker run --name t_c_1 --expose 8080 --env JAVA_HOME=/opt/jdks/jdk1.8.0_212 --workdir /opt/apps/app_0 t_i_0 /bin/bash
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
63258c74cb4b        t_i_0               "/bin/bash"              8 seconds ago       Exited (0) 6 seconds ago                       t_c_1
6a6a3ed5a380        centos              "bash -c 'mkdir -p /…"   3 minutes ago       Exited (0) 3 minutes ago                       t_c_0
[root@docker_host_0 opt]#

    将t_c_1容器的当前状态保存为t_i_1镜像:

[root@docker_host_0 opt]# docker container commit t_c_1 t_i_1
sha256:c5f0d673d958aad49db41e154bf723bb947be257a9999014881ab90e8f155106
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
t_i_1               latest              c5f0d673d958        7 seconds ago       216MB
t_i_0               latest              1aa86a5d25c2        2 minutes ago       216MB
centos              latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_0 opt]#

    以t_i_1为父镜像创建t_c_2容器,并添加命令"bin/startup.sh && tail -f logs/catalina.out":

docker create与docker run都可以为镜像添加命令,区别在于create命令仅添加而不运行,run命令则既添加且运行。本例中运行最终镜像需要挂载jdk环境,否则将报错而启动失败,且将不必要的日志文件编译进镜像中,因此使用create命令而非run命令。

[root@docker_host_0 opt]# docker container create --name t_c_2 t_i_1 bash -c "bin/startup.sh && tail -f logs/catalina.out"
e414c244d72525431607f4f439fe7590600316a97cda17f78d4ee8b1d0c25bf8
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
e414c244d725        t_i_1               "bash -c 'bin/startu…"   6 seconds ago       Created                                        t_c_2
63258c74cb4b        t_i_0               "/bin/bash"              2 minutes ago       Exited (0) 2 minutes ago                       t_c_1
6a6a3ed5a380        centos              "bash -c 'mkdir -p /…"   5 minutes ago       Exited (0) 5 minutes ago                       t_c_0
[root@docker_host_0 opt]#

     将t_c_2容器的当前状态保存为tomcat_app_manual镜像,手动构建完成。

[root@docker_host_0 opt]# docker container commit t_c_2 tomcat_app_manual
sha256:557c9112cb3f132de99f850bf11a5954a15816e30fa45fd2ab01f9c3030f02f1
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
tomcat_app_manual   latest              557c9112cb3f        8 seconds ago        216MB
t_i_1               latest              c5f0d673d958        About a minute ago   216MB
t_i_0               latest              1aa86a5d25c2        3 minutes ago        216MB
centos              latest              9f38484d220f        7 weeks ago          202MB
[root@docker_host_0 opt]#

    查看镜像的属性信息:

inspect命令的--format选项用于以go模板格式化输出,也可以通过shell的grep/awk/sed手动过滤,以查看指定块与字段。

[root@docker_host_0 opt]# docker image inspect --format='{{ .Config.Env }}' tomcat_app_manual
[JAVA_HOME=/opt/jdks/jdk1.8.0_212 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin]
[root@docker_host_0 opt]# docker image inspect --format='{{ .Config.ExposedPorts }}' tomcat_app_manual
map[8080/tcp:{}]
[root@docker_host_0 opt]# docker image inspect --format='{{ .Config.WorkingDir }}' tomcat_app_manual
/opt/apps/app_0
[root@docker_host_0 opt]# docker image inspect --format='{{ .Config.Cmd }}' tomcat_app_manual
[bash -c bin/startup.sh && tail -f logs/catalina.out]
[root@docker_host_0 opt]#

    以名称app_man运行tomcat_app_manual镜像,挂载共享卷并映射端口:

[root@docker_host_0 opt]# docker run -dit --name app_man -p 8080:8080 --mount src=jdks,dst=/opt/jdks,ro tomcat_app_manual
a5c1750f880c3873d14d48dd237f9e47eaa08184117fe4c79e53e001997dcd2e
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                    NAMES
a5c1750f880c        tomcat_app_manual   "bash -c 'bin/startu…"   5 seconds ago       Up 5 seconds                0.0.0.0:8080->8080/tcp   app_man
e414c244d725        t_i_1               "bash -c 'bin/startu…"   6 minutes ago       Created                                              t_c_2
63258c74cb4b        t_i_0               "/bin/bash"              8 minutes ago       Exited (0) 8 minutes ago                             t_c_1
6a6a3ed5a380        centos              "bash -c 'mkdir -p /…"   11 minutes ago      Exited (0) 11 minutes ago                            t_c_0
[root@docker_host_0 opt]#

    容器内的tomcat进程成功启动,并已创建端口映射:

[root@docker_host_0 opt]# docker container top app_man
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                7769                7751                0                   22:25               pts/0               00:00:00            bash -c bin/startup.sh && tail -f logs/catalina.out
root                7815                7769                1                   22:25               pts/0               00:00:02            /opt/jdks/jdk1.8.0_212/bin/java -Djava.util.logging.config.file=/opt/apps/app_0/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /opt/apps/app_0/bin/bootstrap.jar:/opt/apps/app_0/bin/tomcat-juli.jar -Dcatalina.base=/opt/apps/app_0 -Dcatalina.home=/opt/apps/app_0 -Djava.io.tmpdir=/opt/apps/app_0/temp org.apache.catalina.startup.Bootstrap start
root                7816                7769                0                   22:25               pts/0               00:00:00            tail -f logs/catalina.out
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container port app_man
8080/tcp -> 0.0.0.0:8080
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container logs app_man
Using CATALINA_BASE:   /opt/apps/app_0
Using CATALINA_HOME:   /opt/apps/app_0
Using CATALINA_TMPDIR: /opt/apps/app_0/temp
Using JRE_HOME:        /opt/jdks/jdk1.8.0_212
Using CLASSPATH:       /opt/apps/app_0/bin/bootstrap.jar:/opt/apps/app_0/bin/tomcat-juli.jar
Tomcat started.
...
05-May-2019 22:25:55.060 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 521 ms
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_0 opt]#

    发送请求,访问日志显示tomcat正常运行:

tomcat默认的访问日志以日期命名,形式为localhost_access_log.YYYY-MM-DD.txt

[root@docker_host_0 opt]# curl localhost:8080 &> /dev/null
[root@docker_host_0 opt]# docker exec -it app_man tail -f logs/localhost_access_log.$(date +%F).txt
172.17.0.1 - - [05/May/2019:22:31:47 +0000] "GET / HTTP/1.1" 200 11204

    停止容器后,宿主机的端口映射关闭:

[root@docker_host_0 opt]# docker container stop app_man
app_man
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES
a5c1750f880c        tomcat_app_manual   "bash -c 'bin/startu…"   9 minutes ago       Exited (137) 9 seconds ago                       app_man
e414c244d725        t_i_1               "bash -c 'bin/startu…"   15 minutes ago      Created                                          t_c_2
63258c74cb4b        t_i_0               "/bin/bash"              17 minutes ago      Exited (0) 17 minutes ago                        t_c_1
6a6a3ed5a380        centos              "bash -c 'mkdir -p /…"   20 minutes ago      Exited (0) 20 minutes ago                        t_c_0
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# ss -atn | grep 8080
[root@docker_host_0 opt]#

3.1.2 自动构建

    创建名称为Dockerfile的文件,并添加以下内容:

[root@docker_host_0 opt]# vi Dockerfile
FROM centos:latest
COPY apache-tomcat-8.5.40 /opt/apps/app_0
EXPOSE 8080
ENV JAVA_HOME /opt/jdks/jdk1.8.0_212
WORKDIR /opt/apps/app_0
CMD bin/startup.sh && tail -f logs/catalina.out

    在Dockerfile所在目录下,执行build命令构建镜像,名称为tomcat_app_automatic:

[root@docker_host_0 opt]# docker build -t tomcat_app_automatic .
Sending build context to Docker daemon  219.1MB
Step 1/6 : FROM centos:latest
 ---> 9f38484d220f
Step 2/6 : COPY apache-tomcat-8.5.40 /opt/apps/app_0
 ---> a9ec389212f2
Step 3/6 : EXPOSE 8080
 ---> Running in b52093559f48
Removing intermediate container b52093559f48
 ---> 7e52baca9d55
Step 4/6 : ENV JAVA_HOME /opt/jdks/jdk1.8.0_212
 ---> Running in a39dfd747133
Removing intermediate container a39dfd747133
 ---> 9d735d4bf9b1
Step 5/6 : WORKDIR /opt/apps/app_0
 ---> Running in 5137688b2b8e
Removing intermediate container 5137688b2b8e
 ---> c7bf4a13f5ef
Step 6/6 : CMD bin/startup.sh && tail -f logs/catalina.out
 ---> Running in 6e234908cd40
Removing intermediate container 6e234908cd40
 ---> 88d50ce0f132
Successfully built 88d50ce0f132
Successfully tagged tomcat_app_automatic:latest
[root@docker_host_0 opt]#

    REPOSITORY与TAG为<none>的镜像为自动构建过程中生成的中间层,每一层对应一条Dockerfile指令:

[root@docker_host_0 opt]# docker image ls -a
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
tomcat_app_automatic   latest              88d50ce0f132        5 minutes ago       216MB
<none>                 <none>              a9ec389212f2        5 minutes ago       216MB
<none>                 <none>              9d735d4bf9b1        5 minutes ago       216MB
<none>                 <none>              7e52baca9d55        5 minutes ago       216MB
<none>                 <none>              c7bf4a13f5ef        5 minutes ago       216MB
tomcat_app_manual      latest              557c9112cb3f        24 minutes ago      216MB
t_i_1                  latest              c5f0d673d958        26 minutes ago      216MB
t_i_0                  latest              1aa86a5d25c2        28 minutes ago      216MB
centos                 latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_0 opt]#
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker image inspect --format='{{ .ContainerConfig.Cmd }}' 9d735d4bf9b1
[/bin/sh -c #(nop)  ENV JAVA_HOME=/opt/jdks/jdk1.8.0_212]
[root@docker_host_0 opt]# docker image inspect --format='{{ .ContainerConfig.Cmd }}' a9ec389212f2
[/bin/sh -c #(nop) COPY dir:2e81cf3513b112d6ce6d7132e7bca23162bdba7cbf381d72f1b9a7a42c87f19d in /opt/apps/app_0 ]
[root@docker_host_0 opt]# docker image inspect --format='{{ .ContainerConfig.Cmd }}' 7e52baca9d55
[/bin/sh -c #(nop)  EXPOSE 8080]
[root@docker_host_0 opt]# docker image inspect --format='{{ .ContainerConfig.Cmd }}' c7bf4a13f5ef
[/bin/sh -c #(nop) WORKDIR /opt/apps/app_0]
[root@docker_host_0 opt]# docker image inspect --format='{{ .ContainerConfig.Cmd }}' tomcat_app_automatic
[/bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "bin/startup.sh && tail -f logs/catalina.out"]]
[root@docker_host_0 opt]#

    以名称app_auto启动tomcat_app_automatic镜像:

[root@docker_host_0 opt]# docker run -dit --name app_auto -p 8080:8080 --mount src=jdks,dst=/opt/jdks,ro tomcat_app_automatic
57878e669fb99606f85dccf6937a43babaa23c327040c7994657fab2ac0e5acb
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container ls -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                        PORTS                    NAMES
57878e669fb9        tomcat_app_automatic   "/bin/sh -c 'bin/sta…"   5 seconds ago       Up 4 seconds                  0.0.0.0:8080->8080/tcp   app_auto
a5c1750f880c        tomcat_app_manual      "bash -c 'bin/startu…"   22 minutes ago      Exited (137) 13 minutes ago                            app_man
e414c244d725        t_i_1                  "bash -c 'bin/startu…"   28 minutes ago      Created                                                t_c_2
63258c74cb4b        t_i_0                  "/bin/bash"              30 minutes ago      Exited (0) 30 minutes ago                              t_c_1
6a6a3ed5a380        centos                 "bash -c 'mkdir -p /…"   33 minutes ago      Exited (0) 33 minutes ago                              t_c_0
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container top app_auto
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                8305                8287                0                   22:48               pts/0               00:00:00            /bin/sh -c bin/startup.sh && tail -f logs/catalina.out
root                8352                8305                3                   22:48               pts/0               00:00:02            /opt/jdks/jdk1.8.0_212/bin/java -Djava.util.logging.config.file=/opt/apps/app_0/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /opt/apps/app_0/bin/bootstrap.jar:/opt/apps/app_0/bin/tomcat-juli.jar -Dcatalina.base=/opt/apps/app_0 -Dcatalina.home=/opt/apps/app_0 -Djava.io.tmpdir=/opt/apps/app_0/temp org.apache.catalina.startup.Bootstrap start
root                8353                8305                0                   22:48               pts/0               00:00:00            tail -f logs/catalina.out
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container port app_auto
8080/tcp -> 0.0.0.0:8080
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_0 opt]#

    发送请求并查看日志:

[root@docker_host_0 opt]# curl localhost:8080 &> /dev/null
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker exec -it app_auto tail -f logs/localhost_access_log.$(date +%F).txt
172.17.0.1 - - [05/May/2019:22:52:28 +0000] "GET / HTTP/1.1" 200 11204

    查看app_auto容器的运行参数:

[root@docker_host_0 opt]# docker container inspect --format='{{ .Config.Env }}' app_auto
[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin JAVA_HOME=/opt/jdks/jdk1.8.0_212]
[root@docker_host_0 opt]# docker container inspect --format='{{ .Config.ExposedPorts }}' app_auto
map[8080/tcp:{}]
[root@docker_host_0 opt]# docker container inspect --format='{{ .Config.WorkingDir }}' app_auto
/opt/apps/app_0
[root@docker_host_0 opt]# docker container inspect --format='{{ .Config.Cmd }}' app_auto
[/bin/sh -c bin/startup.sh && tail -f logs/catalina.out]
[root@docker_host_0 opt]#

对比两种构建方式,初始状态(centos镜像)与最终状态(tomcat镜像)相同,且目标镜像的大小与运行结果相同。自动构建无需关注中间细节,仅需将功能对应的指令与参数写入到文件,构建过程由docker完成,且自动移除构建过程中产生的中间过渡容器。
Dockerfile中的每一条指令均可以对应到手动构建的命令行选项/参数:

  • docker run centos对应于FROM centos
  • docker cp对应于COPY
  • --expose对应于EXPOST
  • --workdir对应于WORKDIR
  • --env对应于ENV
  • docker container create命令对应于CMD

 3.2 迁移

  • export与save命令分别以容器与镜像标识作为参数,将容器与镜像以tar包的形式导出。两条命令默认将结果输出至STDOUT,可以通过输出重定向或-o/--output选项写入到指定的文件。
  • import命令与load命令将容器与镜像的tar包导入为本地镜像。load命令默认从STDIN读取tar包内容,可以通过输入重定向或-i/--input选项读取指定的文件;import命令直接以tar包文件名为参数进行导入。
  • export导出的容器tar包中,包含可写层中的磁盘文件变更,但不包含镜像构建时指定的参数,包括工作目录与环境变量等信息。import导入容器时可以通过-c/--change选项指定Dockerfile指令,每个选项对应一条双引号内的指令,形式为docker import -c "WORKDIR /opt" -c "EVN JAVA_HOME /opt" 容器tar包
  • 执行导入与导出操作时,应注意命令与操作对象的匹配,如export命令的操作对象为容器而非镜像,save命令的操作对象为镜像而非容器;此外,export命令与save命令导出的tar包中所含的信息不同,因此export/save命令的输出应与import/load命令的输入严格对应。对export导出的容器tar包执行load,或对save导出的镜像tar包执行import,都将导入失败,或导入成功但运行容器失败,以及导致其他未知行为。

    将容器app_auto导出为app_ctr.tar,镜像tomcat_app_automatic导出为app_img.tar。若对export命令指定镜像标识,以及对save命令指定容器标识,则提示容器或镜像不存在,导出失败。

[root@docker_host_0 opt]# docker container ls -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                        PORTS                    NAMES
57878e669fb9        tomcat_app_automatic   "/bin/sh -c 'bin/sta…"   11 minutes ago      Up 11 minutes                 0.0.0.0:8080->8080/tcp   app_auto
a5c1750f880c        tomcat_app_manual      "bash -c 'bin/startu…"   33 minutes ago      Exited (137) 24 minutes ago                            app_man
e414c244d725        t_i_1                  "bash -c 'bin/startu…"   40 minutes ago      Created                                                t_c_2
63258c74cb4b        t_i_0                  "/bin/bash"              42 minutes ago      Exited (0) 42 minutes ago                              t_c_1
6a6a3ed5a380        centos                 "bash -c 'mkdir -p /…"   45 minutes ago      Exited (0) 45 minutes ago                              t_c_0
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker image ls -a
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
tomcat_app_automatic   latest              88d50ce0f132        20 minutes ago      216MB
<none>                 <none>              9d735d4bf9b1        20 minutes ago      216MB
<none>                 <none>              7e52baca9d55        20 minutes ago      216MB
<none>                 <none>              a9ec389212f2        20 minutes ago      216MB
<none>                 <none>              c7bf4a13f5ef        20 minutes ago      216MB
tomcat_app_manual      latest              557c9112cb3f        39 minutes ago      216MB
t_i_1                  latest              c5f0d673d958        41 minutes ago      216MB
t_i_0                  latest              1aa86a5d25c2        43 minutes ago      216MB
centos                 latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker save app_auto > app_img.tar
Error response from daemon: No such image: app_auto
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker export tomcat_app_automatic -o app_ctr.tar
Error response from daemon: No such container: tomcat_app_automatic
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker export app_auto -o app_ctr.tar
[root@docker_host_0 opt]# docker save tomcat_app_automatic -o app_img.tar
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# ll -h app_ctr.tar app_img.tar
-rw------- 1 root root 214M May  5 23:01 app_ctr.tar
-rw------- 1 root root 214M May  5 23:02 app_img.tar
[root@docker_host_0 opt]#

    将两个tar包传输至另一宿主机(docker_host_1),对镜像tar包执行load命令,导入成功,但镜像运行失败:

[root@docker_host_1 opt]# ll -h app_ctr.tar app_img.tar
-rw------- 1 root root 214M May  5 23:06 app_ctr.tar
-rw------- 1 root root 214M May  5 23:06 app_img.tar
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker import app_img.tar app_img:new
sha256:38c69e443d6ff4712e22fcfb4a306776b064a12b3ae1165d5cd725c5dfc4a202
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
app_img             new                 38c69e443d6f        6 seconds ago       224MB
centos              latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker run -it --rm app_img:new /bin/bash
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown.
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker image rm -f app_img:new
Untagged: app_img:new
Deleted: sha256:38c69e443d6ff4712e22fcfb4a306776b064a12b3ae1165d5cd725c5dfc4a202
Deleted: sha256:1e2b7840068294c8c3f1c67cc0d7939eb6ac2135afab7f1065616d9c5c852bd5
[root@docker_host_1 opt]#

     对镜像tar包执行load操作,提示找不到所需的文件,导入失败:

[root@docker_host_1 opt]# docker load -i app_ctr.tar
open /var/lib/docker/tmp/docker-import-466818323/dev/json: no such file or directory
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_1 opt]#
[root@docker_host_1 opt]#

    将容器tar包导入为app_ctr:new,生成的本地镜像中不包含导入前的运行时参数,包括环境变量,开放端口,工作目录与命令,因此容器内的tomcat进程未启动,无法按导入前的状态运行。

[root@docker_host_1 opt]# docker import app_ctr.tar app_ctr:new
sha256:dd4c6121da0e03db43892da94fdb02ee6b0fe5a6e7982f7e40bc37a398497ded
[root@docker_host_1 opt]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
app_ctr             new                 dd4c6121da0e        4 seconds ago       216MB
centos              latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker run -dit --name app_ctr_0 --mount src=jdks,dst=/opt/jdks,ro -p 8080:8080 app_ctr:new
docker: Error response from daemon: No command specified.
See 'docker run --help'.
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker run -dit --name app_ctr_0 --mount src=jdks,dst=/opt/jdks,ro -p 8080:8080 app_ctr:new /bin/bash
6dd2d5243b271259d0f6120aebfc697b280add80b423e5ebf26cbbdf2e597941
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker container top app_ctr_0
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                7678                7660                0                   23:11               pts/0               00:00:00            /bin/bash
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker container logs app_ctr_0
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker container port app_ctr_0
8080/tcp -> 0.0.0.0:8080
[root@docker_host_1 opt]#

    再次导入容器tar包,名称为app_ctr:latest,并指定运行时的参数。运行镜像后,tomcat启动,并可正常访问:

[root@docker_host_1 opt]# docker import app_ctr.tar -c "ENV JAVA_HOME /opt/jdks/jdk1.8.0_212" -c "WORKDIR /opt/apps/app_0" -c "EXPOSE 8080" -c "CMD bin/startup.sh && tail -f logs/catalina.out" app_ctr:latest
sha256:c39af6a5bff5bd1069bb89dec43ea32ade37a356fd05113a6003f7c3ee178863
[root@docker_host_1 opt]#
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
app_ctr             latest              c39af6a5bff5        10 seconds ago      216MB
app_ctr             new                 dd4c6121da0e        4 minutes ago       216MB
centos              latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker image inspect --format='{{ .Config.Env }}' app_ctr:latest
[JAVA_HOME=/opt/jdks/jdk1.8.0_212]
[root@docker_host_1 opt]# docker image inspect --format='{{ .Config.ExposedPorts }}' app_ctr:latest
map[8080/tcp:{}]
[root@docker_host_1 opt]# docker image inspect --format='{{ .Config.WorkingDir }}' app_ctr:latest
/opt/apps/app_0
[root@docker_host_1 opt]# docker image inspect --format='{{ .Config.Cmd }}' app_ctr:latest
[/bin/sh -c bin/startup.sh && tail -f logs/catalina.out]
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker container stop app_ctr_0
app_ctr_0
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker run -dit --name app_ctr_1 --mount src=jdks,dst=/opt/jdks,ro -p 8080:8080 app_ctr:latest
169fce93e085598ffeb188d4861cc4f62aa8cc14b380da6f6397f32f38b8751e
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker container top app_ctr_1
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                7960                7943                0                   23:18               pts/0               00:00:00            /bin/sh -c bin/startup.sh && tail -f logs/catalina.out
root                8008                7960                18                  23:18               pts/0               00:00:02            /opt/jdks/jdk1.8.0_212/bin/java -Djava.util.logging.config.file=/opt/apps/app_0/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /opt/apps/app_0/bin/bootstrap.jar:/opt/apps/app_0/bin/tomcat-juli.jar -Dcatalina.base=/opt/apps/app_0 -Dcatalina.home=/opt/apps/app_0 -Djava.io.tmpdir=/opt/apps/app_0/temp org.apache.catalina.startup.Bootstrap start
root                8009                7960                0                   23:18               pts/0               00:00:00            tail -f logs/catalina.out
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker container logs app_ctr_
Error: No such container: app_ctr_
[root@docker_host_1 opt]# docker container logs app_ctr_
app_ctr_0  app_ctr_1
[root@docker_host_1 opt]# docker container logs app_ctr_1
Using CATALINA_BASE:   /opt/apps/app_0
Using CATALINA_HOME:   /opt/apps/app_0
Using CATALINA_TMPDIR: /opt/apps/app_0/temp
Using JRE_HOME:        /opt/jdks/jdk1.8.0_212
Using CLASSPATH:       /opt/apps/app_0/bin/bootstrap.jar:/opt/apps/app_0/bin/tomcat-juli.jar
Tomcat started.
...
05-May-2019 23:18:37.452 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 628 ms
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# curl localhost:8080 &> /dev/null
[root@docker_host_1 opt]# docker exec -it app_ctr_1 tail -n 1 logs/localhost_access_log.$(date +%F).txt
192.168.9.1 - - [05/May/2019:23:20:00 +0000] "GET /favicon.ico HTTP/1.1" 200 21630
[root@docker_host_1 opt]#

    导入镜像tar包app_img.tar,生成的本地镜像中包含所有导入前的配置参数,包括REPOSITORY,TAG,环境变量,工作目录,开放端口以及运行命令,因此挂载命名卷并运行后,结果与导入前相同:

[root@docker_host_1 opt]# docker container stop app_ctr_1
app_ctr_1
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker load -i app_img.tar
83a1de39c1af: Loading layer  14.39MB/14.39MB
Loaded image: tomcat_app_automatic:latest
[root@docker_host_1 opt]# docker image ls -a
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
app_ctr                latest              c39af6a5bff5        6 minutes ago       216MB
app_ctr                new                 dd4c6121da0e        11 minutes ago      216MB
tomcat_app_automatic   latest              88d50ce0f132        42 minutes ago      216MB
centos                 latest              9f38484d220f        7 weeks ago         202MB
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker image inspect --format='{{ .Config.Env }}' tomcat_app_automatic
[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin JAVA_HOME=/opt/jdks/jdk1.8.0_212]
[root@docker_host_1 opt]# docker image inspect --format='{{ .Config.WorkingDir }}' tomcat_app_automatic
/opt/apps/app_0
[root@docker_host_1 opt]# docker image inspect --format='{{ .Config.ExposedPorts }}' tomcat_app_automatic
map[8080/tcp:{}]
[root@docker_host_1 opt]# docker image inspect --format='{{ .Config.Cmd }}' tomcat_app_automatic
[/bin/sh -c bin/startup.sh && tail -f logs/catalina.out]
[root@docker_host_1 opt]#
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker run -dit --name app_img_0 --mount src=jdks,dst=/opt/jdks,ro -p 8080:8080 tomcat_app_automatic
0193ebdcbf00d688072536162a38ff4f788402d0cc8428c58481a0201151bca0
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker container ls -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                        PORTS                    NAMES
0193ebdcbf00        tomcat_app_automatic   "/bin/sh -c 'bin/sta…"   8 seconds ago       Up 7 seconds                  0.0.0.0:8080->8080/tcp   app_img_0
169fce93e085        app_ctr:latest         "/bin/sh -c 'bin/sta…"   4 minutes ago       Exited (137) 49 seconds ago                            app_ctr_1
6dd2d5243b27        app_ctr:new            "/bin/bash"              11 minutes ago      Exited (137) 4 minutes ago                             app_ctr_0
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker container top app_img_0
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                8455                8437                0                   23:22               pts/0               00:00:00            /bin/sh -c bin/startup.sh && tail -f logs/catalina.out
root                8502                8455                7                   23:22               pts/0               00:00:02            /opt/jdks/jdk1.8.0_212/bin/java -Djava.util.logging.config.file=/opt/apps/app_0/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /opt/apps/app_0/bin/bootstrap.jar:/opt/apps/app_0/bin/tomcat-juli.jar -Dcatalina.base=/opt/apps/app_0 -Dcatalina.home=/opt/apps/app_0 -Djava.io.tmpdir=/opt/apps/app_0/temp org.apache.catalina.startup.Bootstrap start
root                8503                8455                0                   23:22               pts/0               00:00:00            tail -f logs/catalina.out
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# curl localhost:8080 &> /dev/null
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker exec -it app_img_0 tail -f logs/localhost_access_log.$(date +%F).txt
172.17.0.1 - - [05/May/2019:23:23:24 +0000] "GET / HTTP/1.1" 200 11204

参考

https://docs.docker.com/engine/reference/commandline/docker/
https://docs.docker.com/engine/reference/builder/

展开阅读全文
加载中

作者的其它热门文章

打赏
1
4 收藏
分享
打赏
0 评论
4 收藏
1
分享
返回顶部
顶部