Docker 创建镜像(二)

清疚 2022-11-20 08:15 285阅读 0赞

今天我们分析doker镜像的创建过程:

镜像的创建

由容器提交镜像

docker 镜像与容器,使用联合文件技术管理文件。 镜像与容器由一层层的 layer 文件组装而成,如下图:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70

a 、当用镜像模板创建容器时,是直接在镜像的文件层级上,加一层容器读写层

b 、反过来,如果想要创建一个新的镜像,直接把容器对应的所有文件层,转为只读层 即可。commit 命令可达到这个效果:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 1

示例

  1. 创建一个 tomcat 容器

20201027170332142.png

向窝其中加入一个 war 包:

20201027170355915.png

测试 ok

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 2

  1. 要复用这个容器,使用 commit 建一个新镜像

20201027170503835.png

查看镜像

20201027170609147.png

使用新的镜像,创建容器

20201027170812319.png

测试容器

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 3

dockerfile 方式创建容器

虽然使用容器,可以转换成镜像,但不是常规手段。 一情况下,我们使用 dockerfile 方式 最简单的 dockerfile

20201027170934703.png

创建镜像

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 4

使用此镜像运行一个容器

2020102717101615.png

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 5

dockerfile 指令

FROM

FROM {base 镜像 } 必须放在 DOckerfile 的第一行,表示从哪个 baseimage 开始构建

MAINTAINER

可选的,用来标识 image 作者的地方

RUN

RUN 都是启动一个容器、执行命令、然后提交存储层文件变更。 第一层 RUN command1 的执行仅仅是当前进程,一个内存上的变化而已,其结果不会造 成任何文件。 而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能 继承前一层构建过程中的内存变化。 而如果需要将两条命令或者多条命令联合起来执行需要加上&&。 如:cd /usr/local/src && wget xxxxxxx

CMD

CMD 的作用是作为执行 container 时候的默认行为(容器默认的启动命令) 当运行 container 的时候声明了 command ,则不再用 image 中的 CMD 默认所定义 的命令一个 Dockerfile 中只能有一个有效的 CMD ,当定义多个 CMD 的时候,只有最后一个才会 起作用

EXPOSE

EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个 声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助 镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机 端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

entrypoint

entrypoint 的作用是,把整个 container 变成可执行的文件,且不能够通过替换 CMD 的方 法来改变创建 container 的方式。但是可以通过参数传递的方法影响到 container 内部 每个 Dockerfile 只能够包含一个 entrypoint ,多个 entrypoint 只有最后一个有效 当定义了 entrypoint 以后, CMD 只能够作为参数进行传递

ADD & COPY

把 host 上的文件或者目录复制到 image 中(能够进行自动解压压缩包)

ENV

用来设置环境变量,后续的 RUN 可以使用它所创建的环境变量

WORKDIR

用来指定当前工作目录(或者称为当前目录)

USER

运行 RUN 指令的用户

VOLUME

用来创建一个在 image 之外的 mount point

docker 容器的主业

docker 理念里,容器启动时,应当为它指定主业是什么,如 nginx 容器主业就是 nginx 代理服务,tomcat 容器就是 web 服务等等

1 、容器创建时,必须指定主业任务,如不指定,则容器无事可干立即退出。

2 、在 dockerfile 打包镜像时,可以使用 cmd 命令来指定一个默认的主业,如下:

20201027171047623.png

3、既然镜像里是默认主业,即意味着创建容器时,可以覆盖此默认命令,如下

20201027171103378.png

推荐的 ENTRYPOINT 方式

1 、镜像本身应该有稳定的主业,应当指定后即不能更改用途,于是引入 ENTRYPOINT

2 、使用 ENTRYPOINT 字义即容器入口,它不能被 run 中 cmd 覆盖,如下例:

20201027171121960.png

执行: docker build -t nginxx:v3 .

2020102717120350.png

以后使用 nginxx:v3 这个镜像时,只能做 nginx 服务来使用啦

回到我们前面的 tomcat 例子:

2020102717124275.png

创建:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 6

起新容器,查看容器日志

20201027171314444.png

可以看到命令已经更改如果此时,再用 echo 命令去覆盖容器,发现不能成功

20201027171336948.png

echo 命令被当作参数付给 entrypoint 指令

20201027171408645.png

手动打包 springboot 镜像

我们需要对业务项目打包发布,一样需要制作成为业务镜像,供运维使用,下面讲述 springboot 的制作过程:

1 、将 springboot 打好的 jar 包上传

2 、在同级目录下,创建 Dockerfile 文件,内容如下:

20201027171423475.png

3 、 dockerfile 打包业务镜像

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 7

4、启动镜像,即得到业务运行

docker run -d -p 8090:8090 —name member member:v1

20201027171457414.png

5 、浏览器打开页面校验: http://192.168.244.7:8090/

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 8

maven 源码打包用法

更多的情况,我们是直接在运维环境里,上传源码,直接 maven 打包 jar ,然后再进一 步打包成镜像,与手动打包过程类似 如果环境中没有安装 maven ,请手动安装,脚本如下:

sudo yum install -y yum-utils # yum-config-manager —add-repo http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-ap ache-maven.repo # yum-config-manager —enable epel-apache-maven // 安装 maven # yum install -y apache-maven

1 、上传原码到 docker 环境中(一般是 git/svn 直接拉取源码)

20201027171700397.png

2 、 maven 打包

mvn clean package

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 9

生成的 jar 在同级 target 目录下

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 10

3 、执行 docker 命令生成镜像 dockerfile 文件内容

20201027171802503.png

命令创建镜像

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 11

maven 插件打包

前面打 springboot 包的方式,需要手动上传项目 jar 或者源码到服务器(违和感很强), 这对于开发人员日常发布开发环境项目,极为不便 下面,演示一个 maven 插件: docker-maven-plugin 用法 ,来打通环境。

项目环境配置 maven 插件

在我们的工程 pom 中加入 docker-maven-plugin 插件的配置,如下

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 12

现在,我们可以使用 mvn 命令,直接编译项目,打包镜像了 mvn clean package docker:build

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 13

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 14

至此,我们的服务器环境,已经可以直接运行 docker run 镜像得到容器服务了。

发表评论

表情:
评论列表 (有 0 条评论,285人围观)

还没有评论,来说两句吧...

相关阅读

    相关 docker 创建maven 镜像

    创建maven docker镜像 本文将介绍如何创建自己的 maven docker 镜像。由于官方的镜像默认使用中央仓库,在国内构建时会比较慢,虽然缓存是一种策略,但改

    相关 Docker 创建镜像

    今天我们分析doker镜像的创建过程: 镜像的创建 由容器提交镜像 docker 镜像与容器,使用联合文件技术管理文件。 镜像与容器由一层层的 layer 文件组