Dokcer 备忘

如何查看 docker image 文件

可以使用 docker run 命令启动容器并进入容器的 shell,然后浏览容器中的文件系统。以下是如何执行此操作的步骤:

  1. 确保 Docker 已安装并已启动。您可以在终端窗口中运行 docker version 命令来检查 Docker 是否已安装并已启动。

  2. 使用 docker images 命令查找您要查看的 Docker 镜像的 ID 或名称。

  3. 使用 docker run 命令启动容器。例如,如果您要查看名为 my-image 的镜像,可以运行以下命令:

    bash
    1docker run -it my-image /bin/bash

    -it 选项告诉 Docker 在交互式模式下运行容器,并在容器中打开一个 shell。/bin/bash 参数告诉 Docker 在容器中启动 Bash shell。

  4. 在容器的 shell 中,您可以使用常规的 Linux 命令来浏览文件系统。例如,要查看容器中的当前目录,可以运行以下命令:

    bash
    1pwd

    要列出当前目录中的所有文件和子目录,请运行以下命令:

    bash
    1ls -la

    这些命令将在容器的 shell 中执行,并显示容器中的文件系统内容。

  5. 当您完成查看 Docker 镜像时,可以使用 exit 命令退出容器的 shell。

这是查看 Docker 镜像文件的简单方法。请注意,容器中的更改不会保留,因此如果您需要在 Docker 镜像中进行更改,则需要在容器中进行更改,然后将更改保存为新的镜像或提交更改以更新原始镜像。

为了保持干净可以退出容器时销毁,使用如下命令

bash
1docker run --rm -it my-image /bin/bash

Docker 多阶段构建

NextJS with Docker

多阶段构建是一种优化 Docker 镜像构建的方法,它允许您在单个 Dockerfile 中定义多个构建阶段。这种方法使您能够在不同的阶段使用不同的基础镜像,并仅包含所需的文件和依赖项。以下是多阶段构建的一些主要优点:

  1. 减小镜像大小:通过仅在最终镜像中包含运行时所需的文件和依赖项,您可以大大减小 Docker 镜像的大小。这将减少存储空间占用和带宽需求,从而提高部署速度。
  2. 优化构建过程:多阶段构建允许您在不同的构建阶段使用不同的基础镜像,这意味着您可以为每个阶段选择最合适的基础镜像。这有助于提高构建速度和运行时性能。
  3. 提高安全性:由于最终镜像仅包含运行时所需的文件和依赖项,因此可以减少攻击面。这有助于提高应用程序的安全性。
  4. 简化 Dockerfile:多阶段构建使您可以在一个 Dockerfile 中组织构建过程的各个阶段。这有助于提高可维护性,因为所有构建逻辑都集中在一个文件中。
  5. 避免不必要的依赖:多阶段构建允许您在构建过程中仅安装所需的依赖项,从而避免在最终镜像中包含不必要的依赖项。这有助于减小镜像大小并提高安全性。
  6. 更好地利用缓存:多阶段构建可以更好地利用 Docker 的缓存机制。每个构建阶段都有自己的缓存,当您修改 Dockerfile 的某个部分时,只需重新构建受影响的阶段,而不是整个构建过程。这有助于加速构建过程。
  7. 有利于跨团队协作:多阶段构建有助于在构建过程中实现分离关注点。不同的团队成员可以专注于他们擅长的领域,例如编译、测试或部署。这使得协作更加高效和轻松。

综上所述,多阶段构建提供了许多优势,特别是在编译、部署和维护 Docker 镜像时。通过使用多阶段构建,您可以创建更小、更安全且性能更优越的 Docker 镜像。

搭配 GitHub Actions docker/build-push-action 仅执行特定阶段

要在 docker/build-push-action 中仅执行特定阶段,可以在 Dockerfile 中使用 target 选项。target 选项允许您指定要构建到的阶段,而不是构建整个 Dockerfile。首先,需要确保您的 Dockerfile 使用了多阶段构建。

以下是一个简单的 Dockerfile 示例,使用了多阶段构建:

docker
1# 第一阶段 - 依赖安装
2FROM node:14 AS base
3WORKDIR /app
4COPY package*.json ./
5RUN npm install
6
7# 第二阶段 - 构建
8FROM base AS build
9COPY . .
10RUN npm run build
11
12# 第三阶段 - 生产环境
13FROM node:14 AS production
14WORKDIR /app
15COPY --from=build /app/dist /app/dist
16CMD ["npm", "start"]

在这个示例中,我们有三个阶段:basebuildproduction。如果我们希望仅执行 build 阶段,可以在 docker/build-push-action 中使用 target 选项。

以下是一个 .github/workflows/main.yml 文件的示例,仅执行 build 阶段:

yaml
1name: Build Docker Image
2
3on:
4  push:
5    branches:
6      - main
7
8jobs:
9  build:
10    runs-on: ubuntu-latest
11    steps:
12      - name: Check out the code
13        uses: actions/checkout@v2
14
15      - name: Set up Docker Buildx
16        uses: docker/setup-buildx-action@v1
17
18      - name: Login to Docker Hub
19        uses: docker/login-action@v1
20        with:
21          username: ${{ secrets.DOCKER_HUB_USERNAME }}
22          password: ${{ secrets.DOCKER_HUB_PASSWORD }}
23
24      - name: Build Docker Image
25        uses: docker/build-push-action@v2
26        with:
27          context: .
28          tags: your-dockerhub-username/your-image-name:latest
29          target: build

在这个示例中,我们在 with 部分使用了 target 选项,并将其设置为 build。这将确保在构建过程中仅执行 Dockerfilebuild 阶段。

通过使用 target 选项,您可以在 docker/build-push-action 中精确地控制要执行的构建阶段。这可以帮助您根据需要优化构建过程。

Dockerfile 中进行条件判断

在 Dockerfile 中,可以使用 RUN 指令结合 shell 脚本来实现条件判断。通常,这是通过在 RUN 指令中使用 if 语句来完成的。下面是一个使用 bash 作为 shell 的示例:

docker
1FROM ubuntu:20.04
2
3ARG BUILD_ENV
4
5RUN if [ "$BUILD_ENV" = "production" ]; then \
6        echo "Production environment detected. Do something..."; \
7    else \
8        echo "Non-production environment detected. Do something else..."; \
9    fi

在这个示例中,我们首先从 Ubuntu 20.04 基础镜像开始。然后我们使用 ARG 指令定义一个名为 BUILD_ENV 的构建参数。在构建镜像时,可以通过 --build-arg 选项设置此参数的值。

接下来,我们使用 RUN 指令创建一个简单的条件判断。根据 BUILD_ENV 参数的值,我们执行不同的操作。如果 BUILD_ENV 的值等于 "production",则会执行一段描述性的输出。否则,会执行另一段输出。

注意,我们需要使用反斜杠 \ 在多行之间进行换行。同时,使用分号 ; 来分隔不同的 shell 命令。

在构建镜像时,可以通过传递 --build-arg 选项来设置 BUILD_ENV 的值:

bash
1docker build --build-arg BUILD_ENV=production -t your-image-name .

总之,通过在 RUN 指令中使用 shell 脚本,您可以在 Dockerfile 中实现条件判断。这使您可以根据不同的构建参数执行不同的操作,从而创建更灵活的镜像。

搭配 GitHub Actions docker/build-push-action build-args

docker/build-push-action 是一个 GitHub Action,用于构建和推送 Docker 镜像。要在此 Action 中使用构建参数(build args),您需要在构建步骤中将它们传递给 with 部分的 contextbuild-args 属性。

以下是一个使用 docker/build-push-action 的示例 .github/workflows/main.yml 文件,其中包含使用构建参数的方法:

yaml
1name: Build and Push Docker Image
2
3on:
4  push:
5    branches:
6      - main
7
8jobs:
9  build-and-push:
10    runs-on: ubuntu-latest
11    steps:
12      - name: Check out the code
13        uses: actions/checkout@v2
14
15      - name: Set up Docker Buildx
16        uses: docker/setup-buildx-action@v1
17
18      - name: Login to Docker Hub
19        uses: docker/login-action@v1
20        with:
21          username: ${{ secrets.DOCKER_HUB_USERNAME }}
22          password: ${{ secrets.DOCKER_HUB_PASSWORD }}
23
24      - name: Build and Push Docker Image
25        uses: docker/build-push-action@v2
26        with:
27          context: .
28          push: true
29          tags: your-dockerhub-username/your-image-name:latest
30          build-args: |
31            BUILD_ENV=production
32            ANOTHER_ARG=value

在此示例中,我们首先定义了一个 GitHub 工作流,该工作流在向 main 分支推送时触发。然后,在 build-and-push 作业中,我们依次执行以下步骤:

  1. 使用 actions/checkout@v2 检出代码库。
  2. 使用 docker/setup-buildx-action@v1 设置 Docker Buildx。
  3. 使用 docker/login-action@v1 登录到 Docker Hub,以便能够推送镜像。请确保将您的 Docker Hub 凭据存储在 GitHub Secrets 中,并在此处正确引用它们。
  4. 使用 docker/build-push-action@v2 构建并推送 Docker 镜像。在 with 部分,我们设置了 contextpushtags 属性。同时,我们使用 build-args 属性来传递构建参数。在此示例中,我们传递了两个构建参数:BUILD_ENVANOTHER_ARG,并分别设置了它们的值。

通过这种方式,您可以在使用 docker/build-push-action 的 GitHub Actions 工作流中使用构建参数。这有助于您根据需要定制 Docker 镜像的构建过程,实现更高的灵活性。

Docker file 中使用 USER node 导致权限异常,应该怎么解决

如果在Dockerfile中使用USER node导致权限异常,通常是因为在之前的步骤中,某些文件或目录的权限未正确设置,导致node用户无法访问。为了解决这个问题,你需要确保在切换到node用户之前,正确设置了相关文件和目录的权限。

以下是一个修改后的Dockerfile示例,其中我使用chown命令确保了node用户可以访问必要的文件和目录:

docker
1# ...
2# 其他阶段
3# ...
4
5# 第四阶段,runner
6FROM node:lts-alpine AS runner
7
8WORKDIR /usr/app
9
10# 更改工作目录的所有者为 node 用户
11RUN chown -R node:node /usr/app
12
13# 从其他阶段拷贝文件时,确保设置正确的所有者
14COPY --chown=node:node --from=builder /usr/app ./
15
16# 切换到 node 用户
17USER node
18
19CMD ["npm", "run", "start"]

在这个示例中,我在切换到node用户之前,使用chown命令更改了工作目录/usr/app的所有者。同时,我还在COPY命令中使用了--chown选项,确保拷贝过来的文件的所有者是node用户。这样,node用户应该可以正常访问这些文件,而不会出现权限异常。

USER node 的 uid

在 Docker 官方的 node 镜像中,node 用户的 UID(用户标识符)通常为 1000。这是 Linux 系统中非特权用户的默认 UID。当然,这也取决于使用的基础镜像,但对于官方的 node 镜像来说,这是标准的。

您可以在 Dockerfile 中运行以下命令,以确认 node 用户的 UID:

docker
1RUN id -u node

这将在构建过程中输出 node 用户的 UID。请注意,这仅适用于基于 Linux 的 Docker 镜像。

所以存在 Volumes 时,需要修改文件权限为 1000