一、docker commit 定制镜像
不要使用 docker commit 定制镜像,定制镜像应该使用 Dockerfile 来完成
在之前的例子中,我们所使用的都是来自于 Docker Hub 的镜像。直接使用这些镜像是可以满足一定的需求,但有时候我们就需要定制自己的镜像。
$ docker run --name webserver -d -p 80:80 nginx
$ docker exec -it webserver bash
root@3729b97e8226:/# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
root@3729b97e8226:/# exit
exit
// 查看变动
$ docker diff webserver
现在我们定制好了变化,我们希望能将其保存下来形成镜像。
而 Docker 提供了一个 docker commit 命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
$ docker commit webserver lihaixing/docker-nginx:v1
sha256:405bcabb583a2f06fece0c69543eac1fa2e94d84b2c2bf1858ff00cb74b5aec4
// 镜像还在本地,看一下
$ docker image ls lihaixing/docker-nginx
$ docker run --name webserver2 -d -p 81:80 lihaixing/docker-nginx:v1
此外,使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为 黑箱镜像
就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。
二、Dockerfile定制镜像
从刚才的 docker commit 的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件。
如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
Dockerfile 指令介绍 .....
1. FROM 指定基础镜像
指定 基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令,如果不依赖任何镜像
// 这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
FROM scratch
...
在 Docker Hub 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如 nginx、redis、mongo、mysql、httpd、php、tomcat 等;
也有一些方便开发、构建、运行各种语言应用的镜像,如 node、openjdk、python、ruby、golang 等。
2. run 命令
RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一
- shell 格式:RUN <命令>,
exec 格式:RUN ["可执行文件", "参数1", "参数2"]
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
3. CMD 容器启动命令
- shell 格式:CMD <命令>
- exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
- 参数列表格式:CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
4. ENTRYPOINT
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param
5. ENV 设置环境变量
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
ENV NODE_VERSION 7.2.0
ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
6. ARG 构建参数
构建参数和 ENV 的效果一样,都是设置环境变量。
所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。
Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。
灵活的使用 ARG 指令,能够在不修改 Dockerfile 的情况下,构建出不同的镜像。
ARG 指令有生效范围,如果在 FROM 指令之前指定,那么只能用于 FROM 指令中。
ARG <参数名>[=<默认值>]
ARG DOCKER_USERNAME=library
FROM ${DOCKER_USERNAME}/alpine
RUN set -x ; echo ${DOCKER_USERNAME} // 无效
3. docker build 输出镜像
docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
docker build -t mynginx .
docker build -t hello-world https://github.com/docker-library/hello-world.git#master:amd64/hello-world
docker build http://server/context.tar.gz
docker build - < Dockerfile
// 后者
cat Dockerfile | docker build -
docker build - < context.tar.gz
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。