Dokcer 备忘
如何查看 docker image 文件,Docker 指南
如何查看 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 run
与 ls
命令:
这是最直接的方法。您可以运行镜像并列出所需目录的内容,然后退出。例如,要列出一个名为 <image_name>
的镜像的根目录,可以使用:
1docker run --rm <image_name> ls /
这会启动容器,列出根目录的内容,然后因为 --rm
参数,容器将在执行完成后被删除。
在调试时,希望容器继续运行
当你运行一个Docker容器,它会执行默认的命令或你指定的命令。一旦这个命令执行完成,容器就会退出。有时,尤其在调试时,你可能希望容器继续运行,即使其主要的命令已经完成。
使用 tail -f /dev/null
:
它会让容器一直处于运行状态,因为 tail
命令会一直等待新的内容:
1docker run -d <image_name> tail -f /dev/null
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
ENV 和 ARG 的区别
在 Dockerfile 中,ENV
和 ARG
都是用于设置变量的指令,但它们有一些关键的区别:
- 用途和生命周期:
-
ARG:
- 用途:主要用于传递构建参数。
- 生命周期:
ARG
的生命周期仅在 Docker 镜像的构建阶段。一旦构建完成,这些值就不会存在于 Docker 镜像中了,除非它们被ENV
指令明确地持久化。
-
ENV:
- 用途:设置容器运行时的环境变量。
- 生命周期:
ENV
设定的环境变量在镜像构建期间和容器运行期间都是可用的,它们是镜像的一部分并持久化在其中。
- 使用方式:
-
ARG 可以在
docker build
命令中通过--build-arg
选项来设置:1docker build --build-arg MYVAR=value .
在 Dockerfile 中,你可以这样定义和使用它:
1ARG MYVAR=default_value 2COPY $MYVAR /destination/
-
ENV 在 Dockerfile 中直接设置,并在容器运行时自动可用:
1ENV MYVAR=value
- 可见性:
- ARG 只在构建期间可用。但请注意,尽管 ARG 值不会被保存在最终的镜像中,但由于 Docker 的分层结构,它们可能仍在中间层中可见。因此,对于敏感数据(例如密码),仅使用 ARG 可能不足够安全。
- ENV 在构建和运行期间都是可见的,并且被保存在 Docker 镜像中。
- 互操作性:
-
你可以使用
ARG
来初始化ENV
:1ARG MYVAR=default_value 2ENV MYVAR=${MYVAR}
在这种情况下,你可以使用
--build-arg
在构建时设置一个值,然后这个值会被持久化为一个环境变量,在容器运行时仍然可用。
总之,ARG
主要用于影响构建过程,而 ENV
设定的变量主要是为了在运行容器时使用。选择使用哪一个取决于你的具体需求。
GitHub Actions 中使用 Dokcer 打包遇到 JavaScript heap out of memory 的解决办法。
使用环境变量设置 NODE_OPTIONS="--max_old_space_size=4096"
在 Dockerfile 中增加
1ARG NODE_OPTIONS="--max_old_space_size=4096"
安装 docker-compose
Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。
-
下载最新的 Docker Compose 二进制文件:
1sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
-
为下载的二进制文件添加执行权限:
1sudo chmod +x /usr/local/bin/docker-compose
-
验证安装是否成功:
1docker-compose --version
Docker 容器中如何获取宿主机 IP
使用默认网关: 在大多数Docker安装中,容器的默认网关通常是Docker宿主机的IP地址。您可以在容器内部使用以下命令来获取默认网关的地址,该地址通常也是宿主机的地址。
1ip route | awk '/default/ { print $3 }'
docker exec 指定用户
使用 docker exec
命令,并配合 -u
或 --user
选项,可以以特定用户身份在已运行的 Docker 容器内执行命令。此功能在需要用不同于容器默认用户(通常是 root)执行命令时尤其有用。以下是几个例子:
按用户名执行
1docker exec -u username container_id_or_name command
按用户ID执行
1docker exec -u uid container_id_or_name command
指定用户和组
1docker exec -u "username:groupname" container_id_or_name command
以 root 用户执行(默认)
1docker exec container_id_or_name command
示例
假设容器的 ID 是 1234567890ab
,并且你希望以用户名 www-data
执行 ls
命令:
1docker exec -u www-data 1234567890ab ls
本文所描述的 docker exec -u
选项允许在现有 Docker 容器内部以不同用户身份执行命令,这在多用户环境或安全性较高的场景中尤为有用。这样做有助于限制容器内部命令的权限,增加系统的安全性。需要注意的是,指定的用户和组必须在容器的 /etc/passwd
和 /etc/group
文件中存在。