云计算-6-Dockerfile制作镜像

上一章节我们介绍了docker commit制作镜像,生成的镜像被称为黑箱镜像,就是说除了制造镜像的人其他人不知道执行过什么命令,怎么生成的镜像,而且如果时间久远的话,制作人也会忘记操作过程,其维护成本过高。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。

Dockerfile是一个文本文件,其内包含一条条指令,每一条指令构建一层,每一条指令描述如何构建。

我们以我们之前的nginx镜像为例,使用Dockerfile来指定。

vi mynginx_1
FROM nginx:1.21.6
RUN echo '<h1>Welcome My Docker!</h1>' > /usr/share/nginx/html/index.html

这样一个简单的Dockerfile制作成功,涉及FromRUN两条命令。

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 <command>的方式, 
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
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐