持续集成--使用dockerfile构建docker镜像

来源:互联网 发布:读单词软件 日语 编辑:程序博客网 时间:2024/06/07 22:10

一、使用dockerfile构建docker镜像优势

1、简化了镜像的构建过程

2、便于版本控制

二、Dockerfile基本结构

1、基础镜像信息

2、维护者信息

3、镜像操作指令

4、容器启动时执行指令


三、Dockerfile常用指令

1、FROM

获取基础镜像

格式:FROM <image>或FROM <image>:<tag>

例子:FROM docker私服/decision/java:8

注意:

♦ 当不写tag时,相当于拉取的镜像的最新版本(latest版本)

♦ 先从本地查找,本地没有则从docker hub上拉取

♦ 必须是非注释命令的第一个命令

♦ 可以在dockerfile中出现多次

2、MAINTAINER

镜像制作者

格式:MAINTAINER <name>

例子:MAINTAINER XXXXX <XXXXX@XXX.com>

3、RUN

构建指令,可以运行任何被基础镜像支持的命令。

格式:RUN <command> 或 RUN ["executable", "param1", "param2"]

例子:RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'

注意:

♦ 每条RUN指令将在当前镜像基础上执行指定命令,并commit为新的镜像,后续的RUN都是在该层镜像上执行的。

♦ RUN产生的缓存在下一次构建时是不会失效的,可通过docker build --no-cache解决

♦ 将长的或复杂的RUN语句用反斜杠\分割成多行

♦ 使用缓存

♦ 不使用缓存

♦ 使用缓存与不使用缓存时间对比

4、CMD

启动容器时提供一个默认的命令执行选项。如果用户启动容器时指定了运行的命令,则覆盖CMD指定的命令。

格式:CMD ["executable","param1","param2"] 或 CMD ["param1","param2"] 或 CMD command param1 param2

例子:

注意:

♦ CMD命令只有一个,如果有多个则最后一条生效

♦ CMD只在启动容器时执行,build时不执行,而RUN只是在build时执行,后续启动容器时与RUN无关

5、EXPOSE

Docker服务端容器对外映射的本地端口,需要在docker run的时候使用-p或者-P选项生效

格式:EXPOSE <port> [<port>...]

例子:EXPOSE 8080

6、ENV

设置环境变量

格式:ENV <key> <value> 或 ENV <key>=<value>

例子:ENV v1="zhangsan" v2="lisi"

ENV v1 zhangsan

ENV v2 lisi

注意:

♦ 该环境变量不能被CMD命令使用

♦ 设置了后,后续的RUN命令都可以使用,当运行生成的镜像时这些环境变量已然有效,如果需要在运行时更改这些环境变量,可以在运行docker run时添加-e <key>=<value>参数来修改

7、ADD

复制本地主机文件、目录或者远程文件URLS并添加到容器指定路径中

格式:ADD <src>... <dest>

例子:ADD run.sh /test

          ADD http://example.com/foobar /

注意:

♦ <dest>路径必须是绝对路径,如果路径不存在,会自动创建对应目录

♦ <src>路径必须是Dockerfile所在路径的相对路径

♦ 如果<src>路径是一个目录,则只会拷贝该目录下的内容,目录本身不会拷贝

♦ ADD只有在build镜像的时候运行一次,后面运行container的时候不会再重新加载,也就是你不能在运行时通过这种方式向容器中传送文件

♦ 支持自动解压tar文件,会先将tar文件解压,然后将解压后的文件COPY到<dest>目录下

8、COPY

复制文件或者目录并且添加到容器指定路径中

格式:COPY <src>... <dest>

例子:ADD run.sh /test

注意:

♦ 用法同ADD,唯一不同的是不能指定远程文件URLS

♦ 不支持tar文件的自动解压

9、ENTRYPOINT

容器启动后执行的命令

格式:ENTRYPOINT command param1 param2 或 ENTRYPOINT ["executable", "param1", "param2"]

例子:ENTRYPOINT java -Dspring.profiles.active="config,$env" -Dserver.port=${PORT0} -server -Xmx2g -Xms2g -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -Xss2048k -XX:+DisableExplicitGC -XX:+UseG1GC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -jar /XXXX-server-$env.jar

注意:

♦ 配置容器启动后执行的命令,并且不可被docker run提供的参数覆盖,而CMD是可以被覆盖的。如果需要覆盖,则可以使用docker run --entrypoint选项

♦ 每个dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效。

10、VOLUME

持久化数据或共享容器间数据

格式:VOLUME ["/data"]

例子:docker run -d -P 3306:3306 --name test -v 宿主机数据目录:容器中数据目录

注意:

♦ 可通过docker run 挂载,也可在dockerfile中挂载

♦ 可指定共享文件的镜像来源 --volume-form

11、USER

指定运行容器时的用户名或UID,后续的RUN、CMD、 ENTRYPOINT也会使用指定用户

格式:USER <user>[:<group>] 或 USER <UID>[:<GID>]

注意:默认为root用户

12、WORKDIR

为后续的RUN、CMD、 ENTRYPOINT指令配置工作目录。

格式:WORKDIR /path/to/workdir

例子:

WORKDIR /aWORKDIR bWORKDIR cRUN pwd

输出:/a/b/c

注意:

♦ 可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于命令指之前指定的路径。

13、ONBUILD

配置当所创建的镜像作为其他新创建镜像的基础镜像时,所执行的操作命令。

格式:ONBUILD [INSTRUCTION]

例子:

[...]ONBUILD ADD . /app/srcONBUILD RUN /usr/local/bin/python-build --dir /app/src[...]

注意:

♦ 该指令后的命令在使用当前dockerfile创建的镜像A里不执行

♦ 该指令在基于镜像A创建的镜像B运行时才会执行

♦ ONBUILD中定义的指令会在用于生成B镜像的Dockerfile文件的FROM指令之后被执行,可以用来执行一些因为环境而变化的操作,使镜像更加通用。

♦ 如果ONBUILD中的任何一个指令执行失败,则会使FROM指令中断并导致整个BUILD失败。

四、根据Dockerfile创建镜像

1、构建镜像

docker build -t imagename --file dockerfile ./

注意:

运行docker build时,整个构建过程如下:

♦ 读取按照赵顺序ckerfile文件发送到docker daemon

♦ 读取当前目录的所有文件(context),发送到docker daemon

♦ 对dockerfile进行解析,处理成命令加上对应参数结构

♦ 按照顺序循环遍历所有命令,对每个命令调用对应的处理函数进行处理

♦ 每个命令(除了FROM)都会在一个容器执行,执行结果会生成一个新的镜像,为最后生成的镜像打上标签

2、登录docker私服

docker login -u username  -p password  -e email docker私服地址

3、将镜像推到私服

docker push imagename

4、删除本地镜像

docker rmi imagename

5、运行镜像

docker run -d -p 3306:3306  <image>:<tag>

6、进入镜像

docker exec -it <containerid> /bin/bash

五、编写dockerfile的最佳实践

1、使用统一的基础镜像

2、动静分离。经常变化的内容和基本不会变化的内容分开,把不怎么变化的内容放在下层,创建出来不同基础镜像供上层使用。例如可以创建各种语言的基础镜像,在每个基础镜像的基础上继续构建应用级别的镜像。

3、最小原则。只安装必须的东西,因为镜像扩展容易,并且容器运行会很快

4、一个原则:每个镜像只有一个功能。

不要在容器里运行 多个不同功能的进程,每个镜像中只安装一个应用的软件包和文件,需要交互的程序通过容器之间的网络进行交流。这样可以保证模块化,不同的应用可以分开维护和升级,也能减小单个镜像的大小。

5、使用更少的层:尽量把相关内容放到同一个层,使用换行符进行分割, 这样可以进一步减小镜像大小,并且方便查看镜像历史。

6、不要在Dockerfile中单独修改文件的权限。

因为docker镜像是分层的,任何修改都会新增一个层,修改文件或者目录权限也是如此,如果有一个命令单独修改大文件或者目录的权限,会把这些文件复制一份,这样很容易导致镜像很大。

解决方案:

1)添加到Dockerfile之前就把文件的权限和用户设置好

2)容器启动脚本(entrypoint)做这些修改,或者拷贝文件和修改权限放在一起做(这样最终也只是增加一层)

7、利用cache来加快构建速度

如果Docker发现某个层已经存在了,它会直接使用已经存在的层,而不会重新运行一次。

8、版本控制和自动构建

最好把dockerfile和赌赢的应用代码一起放到版本控制中,然后能够自动构建镜像。这样的好处是可以追踪各个版本镜像的内容,方便了解不同镜像的区别,对于调试和回滚都有好处。

另外,如果运行镜像的参数或者环境变量很多,也要有对应的文档给予说明,并且文档要随着dockerfile变化而更新,这样任何人都能参考文档更容易的使用镜像,而不是下载了镜像不知道怎么用。

9、使用.dockerignore文件

在大部分情况下,最好的做法是将每一个Dockerfile文件放到一个空的文件夹里。接着把构建dockerfile所需的文件都添加到这个文件下。为了提高构建效率,可以在这个文件下添加一个.dockerignore文件来排除那些没用的文件和文件夹。

六、实际应用

1、以Python为开发语言的项目部署

dockerfile如下:


jenkins pipeline如下:


2、部署tomcat应用

步骤一:创建Dockerfile,index.jsp

Dockerfile:

index.jsp:

步骤二:通过Dockerfile创建tomcat镜像

docker build -t tomcat ./

步骤三:运行镜像

docker images

docker run -it -P tomcat:latest

步骤四:访问index.jsp

docker ps

http://ip:32778/index.jsp

阅读全文
0 0
原创粉丝点击