通常情况下,构建镜像通常会采用两种方式:
为了解决以上这些问题,Docker v17.05 开始支持多镜像阶段构建 (multistage builds)。只需要编写一个 Dockerfile 即可。通过一段简单的 C 语言代码的编译、执行来具体演示。demo.c 的内容如下:
# include<stdio.h>
int main()
{
printf("%s\n","This is a demo!");
return 0;
}
查看对应的 Dockerfile:
FROM centos:7.8.2003
ENV VERSION 1.0
WORKDIR /demo
COPY demo.c .
RUN yum install -y gcc && \
gcc -v
RUN gcc demo.c -o demo && \
rm -f demo.c && \
yum erase -y gcc && \
cp demo /usr/local/bin/
CMD ["demo"]
感兴趣的小伙伴可以直接将上面的 Dockerfile 和 docker-entrypoint.sh 在本地构建目录创建,执行 docker build -t redis:6.0.5-buster
进行尝试。
多阶段构建一般需要多个 Dockerfile 来完成,由于我们只需要源码编译后的产物。所以我们第一个阶段可以直接使用上文中镜像构建后的产物。第二阶段的 Dockerfile 内容如下:
FROM centos:7.8.2003
ENV VERSION 1.0
WORKDIR /demo
COPY demo /usr/local/bin
CMD ["demo"]
执行构建脚本 bash build.sh
, build.sh
的内容如下:
#!/bin/bash
cd stage-1
docker create --name bin demo:1.0
cd ../stage-2
docker cp bin:/usr/local/bin/demo .
docker rm -f bin
docker build -t demo:2.0 .
构建后得到的 Docker 容器运行结果:
$ docker run --rm -it demo:1.0
This is a demo!
$ docker run --rm -it demo:2.0
This is a demo!
两个容器的环境变量:
$ docker run --rm -it demo:1.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=a52af1bec0af
TERM=xterm
VERSION=1.0
HOME=/root
$ docker run --rm -it demo:2.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=f6618fd1244b
TERM=xterm
VERSION=2.0
HOME=/root
FROM centos:7.8.2003
ENV VERSION 1.0
WORKDIR /demo
COPY demo.c .
RUN yum install -y gcc && \
gcc -v
RUN gcc demo.c -o demo && \
rm -f demo.c && \
yum erase -y gcc && \
cp demo /usr/local/bin/
FROM centos:7.8.2003
COPY --from=0 /usr/local/bin/demo /usr/local/bin/demo
CMD ["demo"]
这种方式构建的 Docker 容器运行结果:
$ docker run --rm -it demo:3.0
This is a demo!
$ docker run --rm -it demo:3.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=7839b3d568db
TERM=xterm
HOME=/root
三个镜像大小对比:
$ docker images|grep demo
demo 3.0 8766031d380a 39 seconds ago 203MB
demo 2.0 7d9c479cb421 10 minutes ago 203MB
demo 1.0 af331209572f 38 minutes ago 350MB