mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-08-10 08:27:25 +00:00
Add blank lines around headers
This commit is contained in:
@@ -30,6 +30,7 @@ COPY . . # 复制到 /app/
|
||||
RUN cd /app
|
||||
RUN echo "hello" > world.txt # 文件在根目录!
|
||||
```
|
||||
|
||||
#### 原因分析
|
||||
|
||||
```dockerfile
|
||||
@@ -110,6 +111,7 @@ RUN npm install
|
||||
COPY . .
|
||||
CMD ["node", "server.js"]
|
||||
```
|
||||
|
||||
#### 2. 使用绝对路径
|
||||
|
||||
```docker
|
||||
@@ -121,6 +123,7 @@ WORKDIR /app
|
||||
|
||||
WORKDIR app
|
||||
```
|
||||
|
||||
#### 3. 不要用 RUN cd
|
||||
|
||||
```docker
|
||||
@@ -133,6 +136,7 @@ RUN cd /app && echo "hello" > world.txt
|
||||
WORKDIR /app
|
||||
RUN echo "hello" > world.txt
|
||||
```
|
||||
|
||||
#### 4. 适时重置 WORKDIR
|
||||
|
||||
```docker
|
||||
|
||||
@@ -55,6 +55,7 @@ USER appuser
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
```
|
||||
|
||||
#### 使用 UID/GID
|
||||
|
||||
```docker
|
||||
@@ -80,6 +81,7 @@ USER nonexistent
|
||||
RUN useradd -r -s /bin/false appuser
|
||||
USER appuser
|
||||
```
|
||||
|
||||
#### 创建用户的方式
|
||||
|
||||
**Debian/Ubuntu**:
|
||||
@@ -139,6 +141,7 @@ chown -R redis:redis /data
|
||||
|
||||
exec gosu redis "$@"
|
||||
```
|
||||
|
||||
#### 为什么不用 su/sudo
|
||||
|
||||
| 问题 | su/sudo | gosu |
|
||||
@@ -208,6 +211,7 @@ CMD ["myapp"]
|
||||
|
||||
CMD ["myapp"] # 以 root 运行
|
||||
```
|
||||
|
||||
#### 2. 使用固定 UID/GID
|
||||
|
||||
便于在宿主机和容器间共享文件:
|
||||
@@ -219,6 +223,7 @@ RUN addgroup -g 1000 -S appgroup && \
|
||||
adduser -u 1000 -S -G appgroup appuser
|
||||
USER 1000:1000
|
||||
```
|
||||
|
||||
#### 3. 多阶段构建中的 USER
|
||||
|
||||
```docker
|
||||
@@ -252,6 +257,7 @@ permission denied: '/app/data.log'
|
||||
```docker
|
||||
RUN mkdir -p /app/data && chown appuser:appuser /app/data
|
||||
```
|
||||
|
||||
#### Q:无法绑定低于 1024 的端口
|
||||
|
||||
非 root 用户无法绑定 80、443 等端口。
|
||||
|
||||
@@ -40,6 +40,7 @@ RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
|
||||
CMD curl -fs http://localhost/ || exit 1
|
||||
```
|
||||
|
||||
#### 命令返回值
|
||||
|
||||
- `0`:成功 (healthy)
|
||||
@@ -82,6 +83,7 @@ HEALTHCHECK CMD curl -f http://localhost/ || exit 1
|
||||
|
||||
HEALTHCHECK CMD wget -q --spider http://localhost/ || exit 1
|
||||
```
|
||||
|
||||
#### 数据库
|
||||
|
||||
```docker
|
||||
@@ -93,6 +95,7 @@ HEALTHCHECK CMD mysqladmin ping -h localhost || exit 1
|
||||
|
||||
HEALTHCHECK CMD redis-cli ping || exit 1
|
||||
```
|
||||
|
||||
#### 自定义脚本
|
||||
|
||||
```docker
|
||||
@@ -178,6 +181,7 @@ $ docker inspect --format '{{json .State.Health}}' mycontainer | jq
|
||||
|
||||
HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1
|
||||
```
|
||||
|
||||
#### 4. 只检查核心依赖
|
||||
|
||||
健康检查应主要关注 **当前服务** 是否可用,而不是检查其下游依赖 (数据库等)。下游依赖的检查应由应用逻辑处理。
|
||||
|
||||
@@ -76,6 +76,7 @@ FROM 基础镜像 ──build──> 读取基础镜像触发器 ──> 执行
|
||||
ONBUILD COPY requirements.txt ./
|
||||
ONBUILD RUN pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### 2. 自动编译代码
|
||||
|
||||
```docker
|
||||
@@ -84,6 +85,7 @@ ONBUILD RUN pip install -r requirements.txt
|
||||
ONBUILD COPY . .
|
||||
ONBUILD RUN go build -o app main.go
|
||||
```
|
||||
|
||||
#### 3. 处理静态资源
|
||||
|
||||
```docker
|
||||
@@ -127,6 +129,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/
|
||||
node:20-onbuild
|
||||
python:3.12-onbuild
|
||||
```
|
||||
|
||||
#### 2. 避免执行耗时操作
|
||||
|
||||
尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作 (如更新系统软件),这会让子镜像构建变得缓慢且不可控。
|
||||
|
||||
@@ -26,6 +26,7 @@ LABEL <key>=<value> <key>=<value> ...
|
||||
LABEL version="1.0"
|
||||
LABEL description="这是一个 Web 应用服务器"
|
||||
```
|
||||
|
||||
#### 定义多个标签:推荐
|
||||
|
||||
```docker
|
||||
@@ -119,6 +120,7 @@ $ docker inspect nginx --format '{{json .Config.Labels}}' | jq
|
||||
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
|
||||
}
|
||||
```
|
||||
|
||||
#### 过滤器
|
||||
|
||||
可以使用标签过滤镜像:
|
||||
|
||||
@@ -31,6 +31,7 @@ SHELL ["/bin/bash", "-c"]
|
||||
|
||||
RUN echo {a..z}
|
||||
```
|
||||
|
||||
#### 2. 增强错误处理
|
||||
|
||||
默认情况下,管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功,整个指令就视为成功。这可能掩盖构建错误。
|
||||
@@ -51,6 +52,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
RUN wget -O - https://invalid-url | tar xz
|
||||
```
|
||||
|
||||
#### 3. Windows 环境
|
||||
|
||||
在 Windows 容器中,经常需要在 `cmd` 和 `powershell` 之间切换。
|
||||
@@ -122,6 +124,7 @@ RUN echo "Using sh again"
|
||||
```docker
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
```
|
||||
|
||||
#### 2. 明确意图
|
||||
|
||||
如果由于脚本需求必须更改 shell,最好在 Dockerfile 中显式声明,而不是依赖默认行为。
|
||||
|
||||
@@ -46,6 +46,7 @@ CMD ["./app"]
|
||||
```bash
|
||||
$ docker build -t go/helloworld:1 -f Dockerfile.one .
|
||||
```
|
||||
|
||||
### 7.17.2 分散到多个 Dockerfile
|
||||
|
||||
另一种方式,就是我们事先在一个 `Dockerfile` 将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要我们编写两个 `Dockerfile` 和一些编译脚本才能将其两个阶段自动整合起来,这种方式虽然可以很好地规避第一种方式存在的风险,但明显部署过程较复杂。
|
||||
@@ -110,6 +111,7 @@ REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
|
||||
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
|
||||
```
|
||||
|
||||
### 7.17.3 使用多阶段构建
|
||||
|
||||
为解决以上问题,Docker v17.05 开始支持多阶段构建 (`multistage builds`)。使用多阶段构建我们就可以很容易解决前面提到的问题,并且只需要编写一个 `Dockerfile`:
|
||||
@@ -168,6 +170,7 @@ FROM golang:alpine as builder
|
||||
```bash
|
||||
$ docker build --target builder -t username/imagename:tag .
|
||||
```
|
||||
|
||||
### 7.17.5 构建时从其他镜像复制文件
|
||||
|
||||
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件,我们也可以复制任意镜像中的文件。
|
||||
|
||||
@@ -54,6 +54,7 @@ server {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.18.2 前端构建
|
||||
|
||||
第一阶段进行前端构建。
|
||||
@@ -74,6 +75,7 @@ RUN set -x ; cd /app \
|
||||
&& mkdir -p public \
|
||||
&& npm run production
|
||||
```
|
||||
|
||||
### 7.18.3 安装 Composer 依赖
|
||||
|
||||
第二阶段安装 Composer 依赖。
|
||||
@@ -93,6 +95,7 @@ RUN set -x ; cd /app \
|
||||
--no-scripts \
|
||||
--prefer-dist
|
||||
```
|
||||
|
||||
### 7.18.4 整合以上阶段所生成的文件
|
||||
|
||||
第三阶段对以上阶段生成的文件进行整合。
|
||||
@@ -118,6 +121,7 @@ RUN set -x ; cd ${LARAVEL_PATH} \
|
||||
&& chmod -R 777 storage \
|
||||
&& php artisan package:discover
|
||||
```
|
||||
|
||||
### 7.18.5 最后一个阶段构建 NGINX 镜像
|
||||
|
||||
```docker
|
||||
@@ -128,6 +132,7 @@ ARG LARAVEL_PATH=/app/laravel
|
||||
COPY laravel.conf /etc/nginx/conf.d/
|
||||
COPY --from=laravel ${LARAVEL_PATH}/public ${LARAVEL_PATH}/public
|
||||
```
|
||||
|
||||
### 7.18.6 构建 Laravel 及 Nginx 镜像
|
||||
|
||||
使用 `docker build` 命令构建镜像。
|
||||
@@ -137,6 +142,7 @@ $ docker build -t my/laravel --target=laravel .
|
||||
|
||||
$ docker build -t my/nginx --target=nginx .
|
||||
```
|
||||
|
||||
### 7.18.7 启动容器并测试
|
||||
|
||||
新建 Docker 网络
|
||||
|
||||
@@ -55,6 +55,7 @@ RUN apt-get update && \
|
||||
apt-get install -y nginx && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
```
|
||||
|
||||
#### 2. 清理缓存
|
||||
|
||||
在安装完软件后,立即清除缓存,可以显著减小镜像体积。
|
||||
@@ -103,6 +104,7 @@ RUN touch hello.txt
|
||||
WORKDIR /app
|
||||
RUN touch hello.txt
|
||||
```
|
||||
|
||||
#### Q:环境变量不生效?
|
||||
|
||||
```docker
|
||||
@@ -136,6 +138,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
go build -o app
|
||||
```
|
||||
|
||||
#### 2. 挂载密钥
|
||||
|
||||
安全地使用 SSH 密钥或 Token,而不将其记录在镜像中。
|
||||
|
||||
@@ -23,6 +23,7 @@ COPY package.json /app/
|
||||
|
||||
COPY config.json /app/settings.json
|
||||
```
|
||||
|
||||
#### 复制多个文件
|
||||
|
||||
```docker
|
||||
@@ -35,6 +36,7 @@ COPY package.json package-lock.json /app/
|
||||
COPY *.json /app/
|
||||
COPY src/*.js /app/src/
|
||||
```
|
||||
|
||||
#### 复制目录
|
||||
|
||||
```docker
|
||||
@@ -77,6 +79,7 @@ COPY app[0-9].js /app/ # app0.js ~ app9.js
|
||||
```docker
|
||||
COPY app.js /usr/src/app/
|
||||
```
|
||||
|
||||
#### 相对路径:基于 WORKDIR
|
||||
|
||||
```docker
|
||||
@@ -84,6 +87,7 @@ WORKDIR /app
|
||||
COPY package.json ./ # 复制到 /app/package.json
|
||||
COPY src/ ./src/ # 复制到 /app/src/
|
||||
```
|
||||
|
||||
#### 自动创建目录
|
||||
|
||||
如果目标目录不存在,Docker 会自动创建:
|
||||
@@ -174,6 +178,7 @@ RUN npm run build
|
||||
FROM nginx:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
```
|
||||
|
||||
#### 使用 --link 优化缓存
|
||||
|
||||
```docker
|
||||
@@ -227,6 +232,7 @@ COPY . .
|
||||
COPY . .
|
||||
RUN npm install
|
||||
```
|
||||
|
||||
#### 2. 使用 .dockerignore
|
||||
|
||||
```docker
|
||||
@@ -238,6 +244,7 @@ COPY . .
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### 3. 明确复制路径
|
||||
|
||||
```docker
|
||||
|
||||
@@ -51,6 +51,7 @@ ADD 会识别并解压以下格式:
|
||||
FROM scratch
|
||||
ADD ubuntu-noble-core-cloudimg-amd64-root.tar.gz /
|
||||
```
|
||||
|
||||
#### 解压过程
|
||||
|
||||
```bash
|
||||
@@ -76,6 +77,7 @@ app.tar.gz 包含: /app/ 目录结果:
|
||||
|
||||
ADD https://example.com/app.zip /app/app.zip
|
||||
```
|
||||
|
||||
#### 为什么不推荐
|
||||
|
||||
| 问题 | 说明 |
|
||||
@@ -127,6 +129,7 @@ ADD rootfs.tar.gz /
|
||||
|
||||
ADD dist.tar.gz /app/
|
||||
```
|
||||
|
||||
#### ❌ 不适合使用 ADD
|
||||
|
||||
```docker
|
||||
@@ -180,6 +183,7 @@ ADD app.tar.gz /app/
|
||||
|
||||
COPY . /app/
|
||||
```
|
||||
|
||||
#### 2. 仅在需要解压时使用 ADD
|
||||
|
||||
```docker
|
||||
@@ -187,6 +191,7 @@ COPY . /app/
|
||||
|
||||
ADD app.tar.gz /app/
|
||||
```
|
||||
|
||||
#### 3. 不要用 ADD 下载文件
|
||||
|
||||
```docker
|
||||
@@ -198,6 +203,7 @@ ADD https://example.com/file.tar.gz /tmp/
|
||||
|
||||
RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app
|
||||
```
|
||||
|
||||
#### 4. 解压后清理
|
||||
|
||||
```docker
|
||||
|
||||
@@ -111,6 +111,7 @@ CMD ["/bin/bash"] + cat /etc/os-release
|
||||
|
||||
CMD service nginx start
|
||||
```
|
||||
|
||||
#### 原因分析
|
||||
|
||||
```bash
|
||||
@@ -126,6 +127,7 @@ CMD service nginx start
|
||||
↓
|
||||
6. 容器主进程(sh)退出 → 容器停止
|
||||
```
|
||||
|
||||
#### 正确做法
|
||||
|
||||
```docker
|
||||
@@ -153,6 +155,7 @@ CMD ["curl", "-s", "http://example.com"]
|
||||
$ docker run myimage # 执行默认命令
|
||||
$ docker run myimage curl -v ... # 完全覆盖
|
||||
```
|
||||
|
||||
#### 搭配 ENTRYPOINT
|
||||
|
||||
```docker
|
||||
@@ -182,6 +185,7 @@ CMD ["python", "app.py"]
|
||||
|
||||
CMD ["sh", "-c", "echo $PATH && python app.py"]
|
||||
```
|
||||
|
||||
#### 2. 确保应用在前台运行
|
||||
|
||||
```docker
|
||||
@@ -196,6 +200,7 @@ CMD ["java", "-jar", "app.jar"]
|
||||
CMD service nginx start
|
||||
CMD systemctl start nginx
|
||||
```
|
||||
|
||||
#### 3. 使用双引号
|
||||
|
||||
```docker
|
||||
@@ -207,6 +212,7 @@ CMD ["node", "server.js"]
|
||||
|
||||
CMD ['node', 'server.js']
|
||||
```
|
||||
|
||||
#### 4. 配合 ENTRYPOINT 使用
|
||||
|
||||
```docker
|
||||
@@ -233,6 +239,7 @@ $ docker run myapp --port 9000
|
||||
CMD ["echo", "first"]
|
||||
CMD ["echo", "second"] # 只有这个生效
|
||||
```
|
||||
|
||||
#### Q:如何在 CMD 中使用环境变量?
|
||||
|
||||
```docker
|
||||
@@ -244,6 +251,7 @@ CMD echo "Port is $PORT"
|
||||
|
||||
CMD ["sh", "-c", "echo Port is $PORT"]
|
||||
```
|
||||
|
||||
#### Q:为什么我的容器不响应 Ctrl+C?
|
||||
|
||||
可能是使用了 shell 格式,信号被 sh 吃掉了:
|
||||
|
||||
@@ -95,6 +95,7 @@ exec: "-i": executable file not found
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### 使用 ENTRYPOINT 解决
|
||||
|
||||
```docker
|
||||
@@ -111,6 +112,7 @@ HTTP/1.1 200 OK
|
||||
...
|
||||
当前 IP:61.148.226.66
|
||||
```
|
||||
|
||||
#### 交互图示
|
||||
|
||||
```bash
|
||||
@@ -160,6 +162,7 @@ fi
|
||||
|
||||
exec "$@"
|
||||
```
|
||||
|
||||
#### 工作流程
|
||||
|
||||
```bash
|
||||
@@ -173,6 +176,7 @@ docker-entrypoint.sh redis-server docker-entrypoint.sh bash
|
||||
└─ exec gosu redis redis-server └─ exec bash
|
||||
(以 redis 用户运行) (以 root 用户运行)
|
||||
```
|
||||
|
||||
#### 关键点
|
||||
|
||||
1. **exec “$@”**:用传入的参数替换当前进程,确保信号正确传递
|
||||
@@ -261,12 +265,14 @@ ENTRYPOINT ["python", "app.py"]
|
||||
|
||||
ENTRYPOINT python app.py
|
||||
```
|
||||
|
||||
#### 2. 提供有意义的默认参数
|
||||
|
||||
```docker
|
||||
ENTRYPOINT ["nginx"]
|
||||
CMD ["-g", "daemon off;"]
|
||||
```
|
||||
|
||||
#### 3. 入口脚本使用 exec
|
||||
|
||||
```bash
|
||||
@@ -278,6 +284,7 @@ CMD ["-g", "daemon off;"]
|
||||
|
||||
exec "$@"
|
||||
```
|
||||
|
||||
#### 4. 处理信号
|
||||
|
||||
确保 ENTRYPOINT 脚本能正确传递信号:
|
||||
|
||||
@@ -21,6 +21,7 @@ ENV <key1>=<value1> <key2>=<value2> ...
|
||||
ENV NODE_VERSION 20.10.0
|
||||
ENV APP_ENV production
|
||||
```
|
||||
|
||||
#### 设置多个变量
|
||||
|
||||
```docker
|
||||
@@ -53,6 +54,7 @@ WORKDIR $APP_HOME
|
||||
|
||||
COPY . $APP_HOME
|
||||
```
|
||||
|
||||
#### 2. 容器运行时使用
|
||||
|
||||
```docker
|
||||
@@ -106,6 +108,7 @@ $ docker run -e APP_ENV=development -e DEBUG=true myimage
|
||||
|
||||
$ docker run --env-file .env myimage
|
||||
```
|
||||
|
||||
#### .env 文件格式
|
||||
|
||||
```bash
|
||||
@@ -165,6 +168,7 @@ RUN apt-get install nginx=${NGINX_VERSION}
|
||||
|
||||
RUN apt-get install nginx=1.25.0
|
||||
```
|
||||
|
||||
#### 2. 不要存储敏感信息
|
||||
|
||||
```docker
|
||||
@@ -178,6 +182,7 @@ ENV DB_PASSWORD=secret123
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### 3. 为应用提供合理默认值
|
||||
|
||||
```docker
|
||||
@@ -185,6 +190,7 @@ ENV APP_ENV=production \
|
||||
APP_PORT=8080 \
|
||||
LOG_LEVEL=info
|
||||
```
|
||||
|
||||
#### 4. 使用有意义的变量名
|
||||
|
||||
```docker
|
||||
@@ -215,12 +221,14 @@ CMD ["python", "app.py", "--port", "$PORT"]
|
||||
|
||||
CMD ["sh", "-c", "python app.py --port $PORT"]
|
||||
```
|
||||
|
||||
#### Q:如何查看容器的环境变量
|
||||
|
||||
```bash
|
||||
$ docker inspect mycontainer --format '{{json .Config.Env}}'
|
||||
$ docker exec mycontainer env
|
||||
```
|
||||
|
||||
#### Q:多行 ENV 还是多个 ENV
|
||||
|
||||
```docker
|
||||
|
||||
@@ -43,6 +43,7 @@ ARG NODE_VERSION=20
|
||||
FROM node:${NODE_VERSION}-alpine
|
||||
RUN echo "Using Node.js $NODE_VERSION"
|
||||
```
|
||||
|
||||
#### 构建时覆盖
|
||||
|
||||
```bash
|
||||
@@ -72,6 +73,7 @@ FROM ${REGISTRY}/${IMAGE_NAME}:20
|
||||
|
||||
RUN echo $REGISTRY # 输出空
|
||||
```
|
||||
|
||||
#### FROM 之后重新声明
|
||||
|
||||
```docker
|
||||
@@ -84,6 +86,7 @@ FROM node:${NODE_VERSION}-alpine
|
||||
ARG NODE_VERSION
|
||||
RUN echo "Node version: $NODE_VERSION"
|
||||
```
|
||||
|
||||
#### 多阶段构建中的 ARG
|
||||
|
||||
```docker
|
||||
@@ -116,6 +119,7 @@ FROM alpine:${ALPINE_VERSION}
|
||||
```bash
|
||||
$ docker build --build-arg ALPINE_VERSION=3.18 .
|
||||
```
|
||||
|
||||
#### 2. 设置软件版本
|
||||
|
||||
```docker
|
||||
@@ -123,6 +127,7 @@ ARG NGINX_VERSION=1.25.0
|
||||
|
||||
RUN curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xz
|
||||
```
|
||||
|
||||
#### 3. 配置构建环境
|
||||
|
||||
```docker
|
||||
@@ -135,6 +140,7 @@ RUN if [ "$ENABLE_DEBUG" = "true" ]; then \
|
||||
npm install --production; \
|
||||
fi
|
||||
```
|
||||
|
||||
#### 4. 配置私有仓库
|
||||
|
||||
```docker
|
||||
@@ -199,6 +205,7 @@ ARG NODE_VERSION=20
|
||||
|
||||
ARG NODE_VERSION
|
||||
```
|
||||
|
||||
#### 2. 不要用 ARG 存储敏感信息
|
||||
|
||||
```docker
|
||||
@@ -211,6 +218,7 @@ RUN echo "password=$DB_PASSWORD" > /app/.env
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### 3. 使用 ARG 提高构建灵活性
|
||||
|
||||
```docker
|
||||
|
||||
@@ -47,6 +47,7 @@ flowchart LR
|
||||
FROM mysql:8.0
|
||||
VOLUME /var/lib/mysql
|
||||
```
|
||||
|
||||
#### 定义多个卷
|
||||
|
||||
```docker
|
||||
@@ -67,6 +68,7 @@ $ docker volume ls
|
||||
DRIVER VOLUME NAME
|
||||
local a1b2c3d4e5f6... # 自动创建的匿名卷
|
||||
```
|
||||
|
||||
#### 2. 可被命名卷覆盖
|
||||
|
||||
```bash
|
||||
@@ -74,6 +76,7 @@ local a1b2c3d4e5f6... # 自动创建的匿名卷
|
||||
|
||||
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
|
||||
```
|
||||
|
||||
#### 3. 可被 Bind Mount 覆盖
|
||||
|
||||
```bash
|
||||
@@ -120,12 +123,14 @@ VOLUME /data
|
||||
FROM postgres:16
|
||||
VOLUME /var/lib/postgresql/data
|
||||
```
|
||||
|
||||
#### 日志目录
|
||||
|
||||
```docker
|
||||
FROM nginx
|
||||
VOLUME /var/log/nginx
|
||||
```
|
||||
|
||||
#### 上传文件目录
|
||||
|
||||
```docker
|
||||
@@ -212,6 +217,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.0
|
||||
FROM postgres:16
|
||||
VOLUME /var/lib/postgresql/data
|
||||
```
|
||||
|
||||
#### 2. 不要在 VOLUME 后修改目录
|
||||
|
||||
```docker
|
||||
@@ -225,6 +231,7 @@ RUN cp init-data.json /app/data/
|
||||
RUN mkdir -p /app/data && cp init-data.json /app/data/
|
||||
VOLUME /app/data
|
||||
```
|
||||
|
||||
#### 3. 文档中说明 VOLUME 用途
|
||||
|
||||
```docker
|
||||
|
||||
@@ -44,6 +44,7 @@ EXPOSE 80 443
|
||||
$ docker inspect nginx --format '{{.Config.ExposedPorts}}'
|
||||
map[80/tcp:{}]
|
||||
```
|
||||
|
||||
#### 2. 配合 -P 使用
|
||||
|
||||
使用 `docker run -P` 时,Docker 会自动映射 EXPOSE 的端口到宿主机随机端口:
|
||||
@@ -75,6 +76,7 @@ flowchart TD
|
||||
Run["docker run -p<br/>实际端口映射<br/>宿主机 ←→ 容器"]
|
||||
Expose ~~~ Run
|
||||
```
|
||||
|
||||
#### 没有 EXPOSE 也能 -p
|
||||
|
||||
```docker
|
||||
@@ -145,6 +147,7 @@ EXPOSE 5432
|
||||
FROM redis
|
||||
EXPOSE 6379
|
||||
```
|
||||
|
||||
#### 2. 使用明确的协议
|
||||
|
||||
```docker
|
||||
@@ -160,6 +163,7 @@ EXPOSE 53/udp
|
||||
|
||||
EXPOSE 53/tcp 53/udp
|
||||
```
|
||||
|
||||
#### 3. 与应用实际端口保持一致
|
||||
|
||||
```docker
|
||||
|
||||
Reference in New Issue
Block a user