Dokcer 备忘
Published by powerfulyang on May 8, 2023
如何查看 docker image 文件
可以使用 docker run
命令启动容器并进入容器的 shell,然后浏览容器中的文件系统。以下是如何执行此操作的步骤:
-
确保 Docker 已安装并已启动。您可以在终端窗口中运行
docker version
命令来检查 Docker 是否已安装并已启动。 -
使用
docker images
命令查找您要查看的 Docker 镜像的 ID 或名称。 -
使用
docker run
命令启动容器。例如,如果您要查看名为my-image
的镜像,可以运行以下命令:1docker run -it my-image /bin/bash
-it
选项告诉 Docker 在交互式模式下运行容器,并在容器中打开一个 shell。/bin/bash
参数告诉 Docker 在容器中启动 Bash shell。 -
在容器的 shell 中,您可以使用常规的 Linux 命令来浏览文件系统。例如,要查看容器中的当前目录,可以运行以下命令:
1pwd
要列出当前目录中的所有文件和子目录,请运行以下命令:
1ls -la
这些命令将在容器的 shell 中执行,并显示容器中的文件系统内容。
-
当您完成查看 Docker 镜像时,可以使用
exit
命令退出容器的 shell。
这是查看 Docker 镜像文件的简单方法。请注意,容器中的更改不会保留,因此如果您需要在 Docker 镜像中进行更改,则需要在容器中进行更改,然后将更改保存为新的镜像或提交更改以更新原始镜像。
为了保持干净可以退出容器时销毁,使用如下命令
1docker run --rm -it my-image /bin/bash
Docker 多阶段构建
多阶段构建是一种优化 Docker 镜像构建的方法,它允许您在单个 Dockerfile 中定义多个构建阶段。这种方法使您能够在不同的阶段使用不同的基础镜像,并仅包含所需的文件和依赖项。以下是多阶段构建的一些主要优点:
- 减小镜像大小:通过仅在最终镜像中包含运行时所需的文件和依赖项,您可以大大减小 Docker 镜像的大小。这将减少存储空间占用和带宽需求,从而提高部署速度。
- 优化构建过程:多阶段构建允许您在不同的构建阶段使用不同的基础镜像,这意味着您可以为每个阶段选择最合适的基础镜像。这有助于提高构建速度和运行时性能。
- 提高安全性:由于最终镜像仅包含运行时所需的文件和依赖项,因此可以减少攻击面。这有助于提高应用程序的安全性。
- 简化 Dockerfile:多阶段构建使您可以在一个 Dockerfile 中组织构建过程的各个阶段。这有助于提高可维护性,因为所有构建逻辑都集中在一个文件中。
- 避免不必要的依赖:多阶段构建允许您在构建过程中仅安装所需的依赖项,从而避免在最终镜像中包含不必要的依赖项。这有助于减小镜像大小并提高安全性。
- 更好地利用缓存:多阶段构建可以更好地利用 Docker 的缓存机制。每个构建阶段都有自己的缓存,当您修改 Dockerfile 的某个部分时,只需重新构建受影响的阶段,而不是整个构建过程。这有助于加速构建过程。
- 有利于跨团队协作:多阶段构建有助于在构建过程中实现分离关注点。不同的团队成员可以专注于他们擅长的领域,例如编译、测试或部署。这使得协作更加高效和轻松。
综上所述,多阶段构建提供了许多优势,特别是在编译、部署和维护 Docker 镜像时。通过使用多阶段构建,您可以创建更小、更安全且性能更优越的 Docker 镜像。
搭配 GitHub Actions docker/build-push-action
仅执行特定阶段
要在 docker/build-push-action
中仅执行特定阶段,可以在 Dockerfile
中使用 target
选项。target
选项允许您指定要构建到的阶段,而不是构建整个 Dockerfile
。首先,需要确保您的 Dockerfile
使用了多阶段构建。
以下是一个简单的 Dockerfile
示例,使用了多阶段构建:
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 /app/dist /app/dist
16CMD ["npm", "start"]
在这个示例中,我们有三个阶段:base
、build
和 production
。如果我们希望仅执行 build
阶段,可以在 docker/build-push-action
中使用 target
选项。
以下是一个 .github/workflows/main.yml
文件的示例,仅执行 build
阶段:
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
。这将确保在构建过程中仅执行 Dockerfile
的 build
阶段。
通过使用 target
选项,您可以在 docker/build-push-action
中精确地控制要执行的构建阶段。这可以帮助您根据需要优化构建过程。
Dockerfile 中进行条件判断
在 Dockerfile 中,可以使用 RUN
指令结合 shell 脚本来实现条件判断。通常,这是通过在 RUN
指令中使用 if
语句来完成的。下面是一个使用 bash
作为 shell 的示例:
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
的值:
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
部分的 context
和 build-args
属性。
以下是一个使用 docker/build-push-action
的示例 .github/workflows/main.yml
文件,其中包含使用构建参数的方法:
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
作业中,我们依次执行以下步骤:
- 使用
actions/checkout@v2
检出代码库。 - 使用
docker/setup-buildx-action@v1
设置 Docker Buildx。 - 使用
docker/login-action@v1
登录到 Docker Hub,以便能够推送镜像。请确保将您的 Docker Hub 凭据存储在 GitHub Secrets 中,并在此处正确引用它们。 - 使用
docker/build-push-action@v2
构建并推送 Docker 镜像。在with
部分,我们设置了context
、push
、tags
属性。同时,我们使用build-args
属性来传递构建参数。在此示例中,我们传递了两个构建参数:BUILD_ENV
和ANOTHER_ARG
,并分别设置了它们的值。
通过这种方式,您可以在使用 docker/build-push-action
的 GitHub Actions 工作流中使用构建参数。这有助于您根据需要定制 Docker 镜像的构建过程,实现更高的灵活性。
Docker file 中使用 USER node 导致权限异常,应该怎么解决
如果在Dockerfile中使用USER node
导致权限异常,通常是因为在之前的步骤中,某些文件或目录的权限未正确设置,导致node
用户无法访问。为了解决这个问题,你需要确保在切换到node
用户之前,正确设置了相关文件和目录的权限。
以下是一个修改后的Dockerfile示例,其中我使用chown
命令确保了node
用户可以访问必要的文件和目录:
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 /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:
1RUN id -u node
这将在构建过程中输出 node
用户的 UID。请注意,这仅适用于基于 Linux 的 Docker 镜像。
所以存在 Volumes 时,需要修改文件权限为 1000