mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-03-10 11:54:37 +00:00
Use vuepress build book
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
This commit is contained in:
@@ -16,7 +16,7 @@ $ touch Dockerfile
|
||||
|
||||
其内容为:
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM nginx
|
||||
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
|
||||
```
|
||||
@@ -33,7 +33,7 @@ RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
|
||||
|
||||
除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 `scratch`。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM scratch
|
||||
...
|
||||
```
|
||||
@@ -48,7 +48,7 @@ FROM scratch
|
||||
|
||||
* *shell* 格式:`RUN <命令>`,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中的 `RUN` 指令就是这种格式。
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
|
||||
```
|
||||
|
||||
@@ -56,7 +56,7 @@ RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
|
||||
|
||||
既然 `RUN` 就像 Shell 脚本一样可以执行命令,那么我们是否就可以像 Shell 脚本一样把每个命令对应一个 RUN 呢?比如这样:
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM debian:stretch
|
||||
|
||||
RUN apt-get update
|
||||
@@ -77,7 +77,7 @@ RUN make -C /usr/src/redis install
|
||||
|
||||
上面的 `Dockerfile` 正确的写法应该是这样:
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM debian:stretch
|
||||
|
||||
RUN buildDeps='gcc libc6-dev make wget' \
|
||||
@@ -142,7 +142,7 @@ docker build [选项] <上下文路径/URL/->
|
||||
|
||||
如果在 `Dockerfile` 中这么写:
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
COPY ./package.json /app/
|
||||
```
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
**注意:docker-compose build 命令暂时不支持 BuildKit**
|
||||
|
||||
下面介绍如何在 Docker CE 18.09+ 版本中使用 `BuildKit` 提供的 `Dockerfile` 新指令来更快、更安全的构建 Docker 镜像。
|
||||
下面介绍如何在 Docker CE 18.09 版本中使用 `BuildKit` 提供的 `Dockerfile` 新指令来更快、更安全的构建 Docker 镜像。
|
||||
|
||||
### 启用 `BuildKit`
|
||||
|
||||
|
||||
148
image/buildx.md
Normal file
148
image/buildx.md
Normal file
@@ -0,0 +1,148 @@
|
||||
## 使用 `Buildx` 构建镜像
|
||||
|
||||
**BuildKit** 是下一代的镜像构建组件,在 https://github.com/moby/buildkit 开源。
|
||||
|
||||
**注意:如果您的镜像构建使用的是云服务商提供的镜像构建服务(Docker Hub 自动构建、腾讯云容器服务、阿里云容器服务等),由于上述服务提供商的 Docker 版本低于 18.09,BuildKit 无法使用,将造成镜像构建失败。建议使用 BuildKit 构建镜像时使用一个新的 Dockerfile 文件(例如 Dockerfile.buildkit)**
|
||||
|
||||
下面介绍如何在 Docker CE 19.03+ 版本中使用 `BuildKit` 提供的 `Dockerfile` 新指令来更快、更安全的构建 Docker 镜像。
|
||||
|
||||
### `Dockerfile` 新增指令详解
|
||||
|
||||
启用 `BuildKit` 之后,我们可以使用下面几个新的指令来加快镜像构建。为了使用 `BuildKit` 我们 **必须** 使用新的 `$ docker buildx build` 命令来构建 Docker 镜像。
|
||||
|
||||
#### `RUN --mount=type=cache`
|
||||
|
||||
目前,几乎所有的程序都会使用依赖管理工具,例如 `Go` 中的 `go mod`、`Node.js` 中的 `npm` 等等,当我们构建一个镜像时,往往会重复的从互联网中获取依赖包,难以缓存,大大降低了镜像的构建效率。
|
||||
|
||||
例如一个前端工程需要用到 `npm`:
|
||||
|
||||
```docker
|
||||
FROM node:alpine as builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json /app/
|
||||
|
||||
RUN npm i --registry=https://registry.npm.taobao.org \
|
||||
&& rm -rf ~/.npm
|
||||
|
||||
COPY src /app/src
|
||||
|
||||
RUN npm run build
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY --from=builder /app/dist /app/dist
|
||||
```
|
||||
|
||||
使用多阶段构建,构建的镜像中只包含了目标文件夹 `dist`,但仍然存在一些问题,当 `package.json` 文件变动时,`RUN npm i && rm -rf ~/.npm` 这一层会重新执行,变更多次后,生成了大量的中间层镜像。
|
||||
|
||||
为解决这个问题,进一步的我们可以设想一个类似 **数据卷** 的功能,在镜像构建时把 `node_modules` 文件夹挂载上去,在构建完成后,这个 `node_modules` 文件夹会自动卸载,实际的镜像中并不包含 `node_modules` 这个文件夹,这样我们就省去了每次获取依赖的时间,大大增加了镜像构建效率,同时也避免了生成了大量的中间层镜像。
|
||||
|
||||
`BuildKit` 提供了 `RUN --mount=type=cache` 指令,可以实现上边的设想。
|
||||
|
||||
```docker
|
||||
FROM node:alpine as builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json /app/
|
||||
|
||||
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
|
||||
--mount=type=cache,target=/root/.npm,id=npm_cache \
|
||||
npm i --registry=https://registry.npm.taobao.org
|
||||
|
||||
COPY src /app/src
|
||||
|
||||
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
|
||||
# --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \
|
||||
npm run build
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
# COPY --from=builder /app/dist /app/dist
|
||||
|
||||
# 为了更直观的说明 from 和 source 指令,这里使用 RUN 指令
|
||||
RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
|
||||
# --mount=type=cache,target/tmp/dist,from=my_app_dist,sharing=locked \
|
||||
mkdir -p /app/dist && cp -r /tmp/dist/* /app/dist
|
||||
```
|
||||
|
||||
第一个 `RUN` 指令执行后,`id` 为 `my_app_npm_module` 的缓存文件夹挂载到了 `/app/node_modules` 文件夹中。多次执行也不会产生多个中间层镜像。
|
||||
|
||||
第二个 `RUN` 指令执行时需要用到 `node_modules` 文件夹,`node_modules` 已经挂载,命令也可以正确执行。
|
||||
|
||||
第三个 `RUN` 指令将上一阶段产生的文件复制到指定位置,`from` 指明缓存的来源,这里 `builder` 表示缓存来源于构建的第一阶段,`source` 指明缓存来源的文件夹。
|
||||
|
||||
上面的 `Dockerfile` 中 `--mount=type=cache,...` 中指令作用如下:
|
||||
|
||||
|Option |Description|
|
||||
|---------------------|-----------|
|
||||
|`id` | `id` 设置一个标志,以便区分缓存。|
|
||||
|`target` (必填项) | 缓存的挂载目标文件夹。|
|
||||
|`ro`,`readonly` | 只读,缓存文件夹不能被写入。 |
|
||||
|`sharing` | 有 `shared` `private` `locked` 值可供选择。`sharing` 设置当一个缓存被多次使用时的表现,由于 `BuildKit` 支持并行构建,当多个步骤使用同一缓存时(同一 `id`)会发生冲突。`shared` 表示多个步骤可以同时读写,`private` 表示当多个步骤使用同一缓存时,每个步骤使用不同的缓存,`locked` 表示当一个步骤完成释放缓存后,后一个步骤才能继续使用该缓存。|
|
||||
|`from` | 缓存来源(构建阶段),不填写时为空文件夹。|
|
||||
|`source` | 来源的文件夹路径。|
|
||||
|
||||
#### `RUN --mount=type=bind`
|
||||
|
||||
该指令可以将一个镜像(或上一构建阶段)的文件挂载到指定位置。
|
||||
|
||||
```docker
|
||||
RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoint,target=/docker-php-entrypoint \
|
||||
cat /docker-php-entrypoint
|
||||
```
|
||||
|
||||
#### `RUN --mount=type=tmpfs`
|
||||
|
||||
该指令可以将一个 `tmpfs` 文件系统挂载到指定位置。
|
||||
|
||||
```docker
|
||||
RUN --mount=type=tmpfs,target=/temp \
|
||||
mount | grep /temp
|
||||
```
|
||||
|
||||
#### `RUN --mount=type=secret`
|
||||
|
||||
该指令可以将一个文件挂载到指定位置。
|
||||
|
||||
```docker
|
||||
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
|
||||
cat /root/.aws/credentials
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker buildx build -t test --secret id=aws,src=$HOME/.aws/credentials .
|
||||
```
|
||||
|
||||
#### `RUN --mount=type=ssh`
|
||||
|
||||
该指令可以挂载 `ssh` 密钥。
|
||||
|
||||
```docker
|
||||
FROM alpine
|
||||
RUN apk add --no-cache openssh-client
|
||||
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
|
||||
RUN --mount=type=ssh ssh git@gitlab.com | tee /hello
|
||||
```
|
||||
|
||||
```bash
|
||||
$ eval $(ssh-agent)
|
||||
$ ssh-add ~/.ssh/id_rsa
|
||||
(Input your passphrase here)
|
||||
|
||||
$ docker buildx build -t test --ssh default=$SSH_AUTH_SOCK .
|
||||
```
|
||||
|
||||
### 清理构建缓存
|
||||
|
||||
执行以下命令清理构建缓存
|
||||
|
||||
```bash
|
||||
$ docker builder prune
|
||||
```
|
||||
|
||||
### 官方文档
|
||||
|
||||
* https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md
|
||||
78
image/buildx_multi-arch-images.md
Normal file
78
image/buildx_multi-arch-images.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# 使用 buildx 构建多种系统架构支持的 Docker 镜像
|
||||
|
||||
在之前的版本中构建多种系统架构支持的 Docker 镜像,要想使用统一的名字必须使用 [`$ docker manifest`](manifest.md) 命令。
|
||||
|
||||
在 Docker 19.03+ 版本中可以使用 `$ docker buildx build` 命令使用 `BuildKit` 构建镜像。
|
||||
|
||||
该命令支持 `--platform` 参数可以同时构建支持多种系统架构的 Docker 镜像,大大简化了构建步骤。
|
||||
|
||||
## 设置环境变量
|
||||
|
||||
`buildx` 命令属于实验特性,必须设置环境变量以使用该命令。
|
||||
|
||||
Linux/macOS
|
||||
|
||||
```bash
|
||||
$ export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
```
|
||||
|
||||
Windows
|
||||
|
||||
```bash
|
||||
$ set $env:DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
```
|
||||
|
||||
## 新建 `builder` 实例
|
||||
|
||||
Docker for Linux 不支持构建 `arm` 架构镜像,我们可以运行一个新的容器让其支持该特性,Docker 桌面版无需进行此项设置。
|
||||
|
||||
```bash
|
||||
$ docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
|
||||
```
|
||||
|
||||
由于 Docker 默认的 `builder` 实例不支持同时指定多个 `--platform`,我们必须首先创建一个新的 `builder` 实例。
|
||||
|
||||
```bash
|
||||
$ docker buildx create --name mybuilder
|
||||
|
||||
$ docker buildx use mybuilder
|
||||
```
|
||||
|
||||
## 构建镜像
|
||||
|
||||
新建 Dockerfile 文件。
|
||||
|
||||
```docker
|
||||
FROM --platform=$TARGETPLATFORM alpine
|
||||
|
||||
RUN uname -a > /os.txt
|
||||
|
||||
CMD cat /os.txt
|
||||
```
|
||||
|
||||
使用 `$ docker buildx build` 命令构建镜像,注意将 `myusername` 替换为自己的 Docker Hub 用户名。
|
||||
|
||||
`--push` 参数表示将构建好的镜像推送到 Docker 仓库。
|
||||
|
||||
```bash
|
||||
$ docker buildx build --platform linux/arm,linux/arm64,linux/amd64 -t myusername/hello . --push
|
||||
|
||||
# 查看镜像信息
|
||||
$ docker buildx imagetools inspect myusername/hello
|
||||
```
|
||||
|
||||
在不同架构运行该镜像,可以得到该架构的信息。
|
||||
|
||||
```bash
|
||||
# arm
|
||||
$ docker run -it --rm myusername/hello
|
||||
Linux buildkitsandbox 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 armv7l Linux
|
||||
|
||||
# arm64
|
||||
$ docker run -it --rm myusername/hello
|
||||
Linux buildkitsandbox 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 aarch64 Linux
|
||||
|
||||
# amd64
|
||||
$ docker run -it --rm myusername/hello
|
||||
Linux buildkitsandbox 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 Linux
|
||||
```
|
||||
@@ -21,7 +21,7 @@ $ docker run --name webserver -d -p 80:80 nginx
|
||||
|
||||
直接用浏览器访问的话,我们会看到默认的 Nginx 欢迎页面。
|
||||
|
||||
<img src="_images/images-mac-example-nginx.png" width="80%" >
|
||||

|
||||
|
||||
现在,假设我们非常不喜欢这个欢迎页面,我们希望改成欢迎 Docker 的文字,我们可以使用 `docker exec` 命令进入容器,修改其内容。
|
||||
|
||||
@@ -38,7 +38,7 @@ exit
|
||||
|
||||
现在我们再刷新浏览器的话,会发现内容被改变了。
|
||||
|
||||
<img src="_images/images-create-nginx-docker.png" width="80%" >
|
||||

|
||||
|
||||
我们修改了容器的文件,也就是改动了容器的存储层。我们可以通过 `docker diff` 命令看到具体的改动。
|
||||
|
||||
|
||||
5
image/demo/multi-arch/Dockerfile
Normal file
5
image/demo/multi-arch/Dockerfile
Normal file
@@ -0,0 +1,5 @@
|
||||
FROM --platform=$TARGETPLATFORM alpine
|
||||
|
||||
RUN uname -a > /os.txt
|
||||
|
||||
CMD cat /os.txt
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
我们知道使用镜像创建一个容器,该镜像必须与 Docker 宿主机系统架构一致,例如 `Linux x86_64` 架构的系统中只能使用 `Linux x86_64` 的镜像创建容器。
|
||||
|
||||
> macOS 除外,其使用了 [binfmt_misc](https://docs.docker.com/docker-for-mac/multi-arch/) 提供了多种架构支持,在 macOS 系统上 (x86_64) 可以运行 arm 等其他架构的镜像。
|
||||
> Windows、macOS 除外,其使用了 [binfmt_misc](https://docs.docker.com/docker-for-mac/multi-arch/) 提供了多种架构支持,在 Windows、macOS 系统上 (x86_64) 可以运行 arm 等其他架构的镜像。
|
||||
|
||||
例如我们在 `Linux x86_64` 中构建一个 `username/test` 镜像。
|
||||
|
||||
```Dockerfile
|
||||
```docker
|
||||
FROM alpine
|
||||
|
||||
CMD echo 1
|
||||
|
||||
@@ -26,7 +26,7 @@ func main(){
|
||||
|
||||
编写 `Dockerfile.one` 文件
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM golang:1.9-alpine
|
||||
|
||||
RUN apk --no-cache add git ca-certificates
|
||||
@@ -56,7 +56,7 @@ $ docker build -t go/helloworld:1 -f Dockerfile.one .
|
||||
|
||||
例如,编写 `Dockerfile.build` 文件
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM golang:1.9-alpine
|
||||
|
||||
RUN apk --no-cache add git
|
||||
@@ -71,7 +71,7 @@ RUN go get -d -v github.com/go-sql-driver/mysql \
|
||||
|
||||
编写 `Dockerfile.copy` 文件
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk --no-cache add ca-certificates
|
||||
@@ -125,7 +125,7 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
|
||||
|
||||
例如,编写 `Dockerfile` 文件
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM golang:1.9-alpine as builder
|
||||
|
||||
RUN apk --no-cache add git
|
||||
@@ -172,7 +172,7 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
|
||||
|
||||
我们可以使用 `as` 来为某一阶段命名,例如
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM golang:1.9-alpine as builder
|
||||
```
|
||||
|
||||
@@ -186,6 +186,6 @@ $ docker build --target builder -t username/imagename:tag .
|
||||
|
||||
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件,我们也可以复制任意镜像中的文件。
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
$ COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
|
||||
```
|
||||
|
||||
@@ -50,7 +50,7 @@ server {
|
||||
|
||||
第一阶段进行前端构建。
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM node:alpine as frontend
|
||||
|
||||
COPY package.json /app/
|
||||
@@ -69,7 +69,7 @@ RUN cd /app \
|
||||
|
||||
第二阶段安装 Composer 依赖。
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM composer as composer
|
||||
|
||||
COPY database/ /app/database/
|
||||
@@ -89,7 +89,7 @@ RUN cd /app \
|
||||
|
||||
第三阶段对以上阶段生成的文件进行整合。
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM php:7.2-fpm-alpine as laravel
|
||||
|
||||
ARG LARAVEL_PATH=/app/laravel
|
||||
@@ -113,7 +113,7 @@ RUN cd ${LARAVEL_PATH} \
|
||||
|
||||
### 最后一个阶段构建 NGINX 镜像
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM nginx:alpine as nginx
|
||||
|
||||
ARG LARAVEL_PATH=/app/laravel
|
||||
@@ -164,7 +164,7 @@ $ docker run -it --rm --network=laravel -p 8080:80 my/nginx
|
||||
|
||||
完整的 `Dockerfile` 文件如下。
|
||||
|
||||
```dockerfile
|
||||
```docker
|
||||
FROM node:alpine as frontend
|
||||
|
||||
COPY package.json /app/
|
||||
|
||||
Reference in New Issue
Block a user