云计算-6-Dockerfile制作镜像
上一章节我们介绍了docker commit制作镜像,生成的镜像被称为黑箱镜像,就是说除了制造镜像的人其他人不知道执行过什么命令,怎么生成的镜像,而且如果时间久远的话,制作人也会忘记操作过程,其维护成本过高。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
Dockerfile是一个文本文件,其内包含一条条指令,每一条指令构建一层,每一条指令描述如何构建。
我们以我们之前的nginx镜像为例,使用Dockerfile来指定。
vi mynginx_1
FROM nginx:1.21.6
RUN echo '
Welcome My Docker!
' > /usr/share/nginx/html/index.html
这样一个简单的Dockerfile制作成功,涉及From和RUN两条命令。
FROM指定基础镜像
定制镜像就是以一个镜像为基础,在其基础上进行定制我们需要的特定镜像。FROM是指定基础镜像,所以FROM指令是Dockerfile文件必须的指令,并且必须是第一条指令。
在Docker的官方仓库中有很多高质量的官方镜像,可以直接拿来使用,例如centos、nginx、redis、mysql等;还存在很多方便我们**开发、构建、运行各种语言的应用镜像,例如openjdk、python、node
等。可以在这些官方镜像中寻找适合我们的镜像作为基础镜像,进行定制。
当然有时候我们可能没有找到合适的服务镜像,那么我们可以根据基础的操作系统镜像例如Centos、debina、ubuntu等为基础镜像,去制作我们想要的特定镜像。
scratch虚拟镜像
Docker中存在一个虚拟的镜像scratch
,就是一个空白镜像,如果用scratch作为基础镜像,那就是我们没有任何基础镜像,FROM下的第一行指令是第一层的开始。
这样使用空白镜像scratch作为基础镜像的方法非常多,对于Linux环境下静态编译的程序来说,并不需要操作系统提供运行支持,所需要的一切库都已经在可执行文件中因此直接REOM scratch会使得镜像体积更小。使用 Go 语言 开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go 是特别适合容器微服务架构的语言的原因之一
RUN执行命令
RUN指令是用来执行命令行的命令,有两种格式:
shell格式:RUN <命令> ( shell 形式, /bin/sh -c 的方式运行,避免破坏shell字符串) ,就像我们直接在命令行中输入命令一样,刚才我们写的制定特质的nginx的Dockerfile就是使用的指令格式。
RUN echo '<h1>Welcome My Docker!</h1>' > /usr/share/nginx/html/index.html
exec 格式:RUN ["executable", "param1", "param2"],exec形式可以避免破坏shell字符串,并使用不包含指定shell可执行文件的基本映像运行RUN命令。可以使用SHELL命令更改shell形式的默认shell。 在shell形式中,您可以使用\(反斜杠)将一条
RUN指令继续到下一行
RUN /bin/bash -c 'source $HOME/.bashrc; \ echo $HOME' #上面等于下面这种写法 RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME' RUN echo '<h1>Welcome My Docker!</h1>' > /usr/share/nginx/html/index.html #上面等同于下面 RUN /bin/sh -c echo '<h1>Welcome My Docker!</h1>' > /usr/share/nginx/html/index.html RUN ["/bin/sh","-c","echo '<h1>Welcome My Docker!</h1>' > /usr/share/nginx/html/index.html"]
那么如果我们将上面nginx的Dockerfile修改为如下:
vi mynginx_2 FROM nginx:1.21.6 RUN echo '<h1>Welcome My Docker!</h1>' > /usr/share/nginx/html/index.html RUN ["/bin/sh","-c","echo '<h1>Welcome My Docker11!</h1>' > /usr/share/nginx/html/index.html"] ——
构建镜像
我们根据mynginx_1和mynginx_2去构建镜像
docker build -t mynginx:v1 -f /root/mynginx_1 . docker build -t mynginx:v2 -f /root/mynginx_2 .
分别运行这两个镜像:
docker run --name mynginx2 -p 8080:80 -d mynginx:v1
docker run --name mynginx2 -p 8082:80 -d mynginx:v2
注: -f 表示指定Dockerfile路
通过以上的图我们可以得出一个结论:
1. shell 是 /bin/sh -c 的方式,
2. exec ["/bin/sh","-c",command] 的方式== shell方式
也就是exec 默认方式不会进行变量替换
其他Docker build用法
直接用 Git repo 进行构建
docker build
还支持从 URL 构建,比如可以直接从 Git repo 中构建:
# $env:DOCKER_BUILDKIT=0 # export DOCKER_BUILDKIT=0 $ docker build -t hello-world https://github.com/docker-library/hello-world.git#master:amd64/hello-world Step 1/3 : FROM scratch ---> Step 2/3 : COPY hello / ---> ac779757d46e Step 3/3 : CMD ["/hello"] ---> Running in d2a513a760ed Removing intermediate container d2a513a760ed ---> 038ad4142d2b Successfully built 038ad4142d2b
用给定的 tar 压缩包构建
$ docker build http://server/context.tar.gz