mirror of
https://github.com/yeasy/docker_practice.git
synced 2025-08-02 22:11:38 +00:00
Use vuepress build book
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
|
||||
在某些情况下,这个自动解压缩的功能非常有用,比如官方镜像 `ubuntu` 中:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM scratch
|
||||
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
|
||||
...
|
||||
@@ -24,7 +24,7 @@ ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
|
||||
|
||||
在使用该指令的时候还可以加上 `--chown=<user>:<group>` 选项来改变文件的所属用户及所属组。
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
ADD --chown=55:mygroup files* /mydir/
|
||||
ADD --chown=bin files* /mydir/
|
||||
ADD --chown=1 files* /mydir/
|
||||
|
@@ -14,13 +14,13 @@
|
||||
|
||||
如果使用 `shell` 格式的话,实际的命令会被包装为 `sh -c` 的参数的形式进行执行。比如:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
CMD echo $HOME
|
||||
```
|
||||
|
||||
在实际执行中,会将其变更为:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
CMD [ "sh", "-c", "echo $HOME" ]
|
||||
```
|
||||
|
||||
@@ -32,7 +32,7 @@ Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是
|
||||
|
||||
一些初学者将 `CMD` 写为:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
CMD service nginx start
|
||||
```
|
||||
|
||||
@@ -44,6 +44,6 @@ CMD service nginx start
|
||||
|
||||
正确的做法是直接执行 `nginx` 可执行文件,并且要求以前台形式运行。比如:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
|
@@ -9,13 +9,13 @@
|
||||
|
||||
`COPY` 指令将从构建上下文目录中 `<源路径>` 的文件/目录复制到新的一层的镜像内的 `<目标路径>` 位置。比如:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
COPY package.json /usr/src/app/
|
||||
```
|
||||
|
||||
`<源路径>` 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 [`filepath.Match`](https://golang.org/pkg/path/filepath/#Match) 规则,如:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
COPY hom* /mydir/
|
||||
COPY hom?.txt /mydir/
|
||||
```
|
||||
@@ -26,7 +26,7 @@ COPY hom?.txt /mydir/
|
||||
|
||||
在使用该指令的时候还可以加上 `--chown=<user>:<group>` 选项来改变文件的所属用户及所属组。
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
COPY --chown=55:mygroup files* /mydir/
|
||||
COPY --chown=bin files* /mydir/
|
||||
COPY --chown=1 files* /mydir/
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
假设我们需要一个得知自己当前公网 IP 的镜像,那么可以先用 `CMD` 来实现:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM ubuntu:18.04
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y curl \
|
||||
@@ -48,7 +48,7 @@ $ docker run myip curl -s https://ip.cn -i
|
||||
|
||||
这显然不是很好的解决方案,而使用 `ENTRYPOINT` 就可以解决这个问题。现在我们重新用 `ENTRYPOINT` 来实现这个镜像:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM ubuntu:18.04
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y curl \
|
||||
@@ -91,7 +91,7 @@ Connection: keep-alive
|
||||
|
||||
这些准备工作是和容器 `CMD` 无关的,无论 `CMD` 为什么,都需要事先进行一个预处理的工作。这种情况下,可以写一个脚本,然后放入 `ENTRYPOINT` 中去执行,而这个脚本会将接到的参数(也就是 `<CMD>`)作为命令,在脚本最后执行。比如官方镜像 `redis` 中就是这么做的:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM alpine:3.4
|
||||
...
|
||||
RUN addgroup -S redis && adduser -S -G redis redis
|
||||
|
@@ -16,7 +16,7 @@ ENV VERSION=1.0 DEBUG=on \
|
||||
|
||||
定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。比如在官方 `node` 镜像 `Dockerfile` 中,就有类似这样的代码:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
ENV NODE_VERSION 7.2.0
|
||||
|
||||
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
|
||||
|
@@ -25,7 +25,7 @@
|
||||
|
||||
假设我们有个镜像是个最简单的 Web 服务,我们希望增加健康检查来判断其 Web 服务是否在正常工作,我们可以用 `curl` 来帮助判断,其 `Dockerfile` 的 `HEALTHCHECK` 可以这么写:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM nginx
|
||||
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||
HEALTHCHECK --interval=5s --timeout=3s \
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
假设我们要制作 Node.js 所写的应用的镜像。我们都知道 Node.js 使用 `npm` 进行包管理,所有依赖、配置、启动信息等会放到 `package.json` 文件里。在拿到程序代码后,需要先进行 `npm install` 才可以获得所有需要的依赖。然后就可以通过 `npm start` 来启动应用。因此,一般来说会这样写 `Dockerfile`:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM node:slim
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
@@ -24,7 +24,7 @@ CMD [ "npm", "start" ]
|
||||
|
||||
那么我们可不可以做一个基础镜像,然后各个项目使用这个基础镜像呢?这样基础镜像更新,各个项目不用同步 `Dockerfile` 的变化,重新构建后就继承了基础镜像的更新?好吧,可以,让我们看看这样的结果。那么上面的这个 `Dockerfile` 就会变为:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM node:slim
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
@@ -33,7 +33,7 @@ CMD [ "npm", "start" ]
|
||||
|
||||
这里我们把项目相关的构建指令拿出来,放到子项目里去。假设这个基础镜像的名字为 `my-node` 的话,各个项目内的自己的 `Dockerfile` 就变为:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM my-node
|
||||
COPY ./package.json /app
|
||||
RUN [ "npm", "install" ]
|
||||
@@ -46,7 +46,7 @@ COPY . /app/
|
||||
|
||||
`ONBUILD` 可以解决这个问题。让我们用 `ONBUILD` 重新写一下基础镜像的 `Dockerfile`:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM node:slim
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
@@ -58,7 +58,7 @@ CMD [ "npm", "start" ]
|
||||
|
||||
这次我们回到原始的 `Dockerfile`,但是这次将项目相关的指令加上 `ONBUILD`,这样在构建基础镜像的时候,这三行并不会被执行。然后各个项目的 `Dockerfile` 就变成了简单地:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM my-node
|
||||
```
|
||||
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
当然,和 `WORKDIR` 一样,`USER` 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
RUN groupadd -r redis && useradd -r -g redis redis
|
||||
USER redis
|
||||
RUN [ "redis-server" ]
|
||||
@@ -14,7 +14,7 @@ RUN [ "redis-server" ]
|
||||
|
||||
如果以 `root` 执行的脚本,在执行期间希望改变身份,比如希望以某个已经建立好的用户来运行某个服务进程,不要使用 `su` 或者 `sudo`,这些都需要比较麻烦的配置,而且在 TTY 缺失的环境下经常出错。建议使用 [`gosu`](https://github.com/tianon/gosu)。
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
# 建立 redis 用户,并使用 gosu 换另一个用户执行命令
|
||||
RUN groupadd -r redis && useradd -r -g redis redis
|
||||
# 下载 gosu
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
之前我们说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中,后面的章节我们会进一步介绍 Docker 卷的概念。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 `Dockerfile` 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
VOLUME /data
|
||||
```
|
||||
|
||||
|
Reference in New Issue
Block a user