docker常见使用技巧

1. 区别

1.1 多阶段构建

你可以在一个 Dockerfile 中定义多个构建阶段。例如,一个阶段用来编译代码(包含所有开发依赖),另一个阶段只把编译好的产物复制到一个干净的基础镜像中。

1.2 CMD vs. ENTRYPOINT:容器的“使命”与“参数”

  • 想象一下,你的容器是一个“命令行工具”。
  • ENTRYPOINT : 定义了这个工具的“程序本身” 。它是固定的,是容器的核心使命。比如,这个工具就是 git 。
  • CMD : 定义了这个工具的“默认参数” 。如果用户不指定任何参数,就用这个。比如, git 的默认参数是 –help
  • CMD 被覆盖,ENTRYPOINT 被用来传参数用
1
2
3
4
# 怎么都会执行 `docker-entrypoint.sh`,你可以选择覆盖 cmd

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["redis-server"]

1.3 Volume vs. Bind Mount

这两种都是将数据持久化到容器之外的方法,但管理方式和适用场景截然不同。

  • Bind Mount (绑定挂载) : 像是你已有的“私家别墅” 。你告诉 Docker:“把我的这个文件夹(别墅)直接给容器用”。你对这个文件夹有完全的控制权。
    • 将主机上的文件或目录直接挂载到容器中
    • ✅ 更好的可移植性
  • Volume (数据卷) : 像是 Docker 为你管理的“精装公寓” 。你不用关心公寓在哪,只管拎包入住(存数据)。Docker 负责创建、管理和清理。

    • 由 Docker 管理的存储空间,存储在 Docker 主机的特定目录下(Linux 通常在 /var/lib/docker/volumes/
    • ❌ 依赖主机路径

看冒号 (:) 左边的部分:

  • 如果它包含 /、./、../ (在 Linux/macOS) 或 \ (在 Windows),那么它一定是 Bind Mount。 因为你在指定一个明确的、存在于宿主机文件系统上的路径。
  • 如果它只是一个简单的字符串,不包含任何路径分隔符,那么它一定是 Volume。 因为你只是在给 Docker 一个名字,让 Docker 自己去管理这个存储空间。
1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3'
services:
app:
image: myapp
volumes:
# Bind Mount - 开发时的代码
- ./src:/app/src
# Volume - 持久化数据
- app-data:/app/data
# Bind Mount - 配置文件(只读)
- ./config/app.conf:/app/config/app.conf:ro
volumes:
app-data:

2. 使用技巧

2.1 指定 IP 执行命令

DOCKER_HOST 是 Docker 的一个环境变量,用于指定 Docker 客户端要连接的 Docker 守护进程(daemon)的地址。

1
DOCKER_HOST=ssh://root@10.133.0.21 docker ps

2.2 查看docker 实时监控

1
docker stats  

2.3 告别宿主机

1
2
3
# 可以轻松切换不同版本的客户端
docker run -it --rm redis:6 redis-cli -h 10.0.114.5
docker run -it --rm redis:7 redis-cli -h 10.0.114.5
  1. 无需本地安装 Redis 客户端,保持本地环境清洁。
  2. 可以轻松切换不同版本的客户端。
  3. -rm 确保容器用完即删,不占用系统资源。
  4. Docker 容器默认可以访问宿主机能访问的网络。

2.4 多利用 docker-compose

  1. 提前拷贝package 缓存
  2. 利用数据卷防止 node_modules 被覆盖
  3. 利用 docker-compose 脚本避免复杂启动参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
FROM node:lts-alpine

RUN apk add --no-cache git openssh-client

RUN npm config set registry https://registry.npmmirror.com

WORKDIR /app

# 【关键】将 node_modules 的可执行文件目录添加到环境变量 PATH 中
ENV PATH /app/node_modules/.bin:$PATH
# 这是利用 Docker 缓存的关键!只要这两个文件不变,下面的 npm install 就不会重新执行。
COPY package*.json ./

# 2. 安装 hexo-cli 和项目所有依赖
# --production=false 确保 devDependencies 也被安装
RUN npm install --production=false hexo-cli && npm install --production=false

# 3. 拷贝你博客的所有其他文件(比如 markdown 文章、主题配置等)
# 这一步放在最后,因为这些文件是你最常修改的
COPY . .

# 暴露 hexo server 的默认端口
EXPOSE 4000

# 设置容器启动时默认执行的命令
CMD ["hexo", "server"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
services:
# 测试
hexo-liuvv:
build:
context: .
dockerfile: Dockerfile
image: my-hexo-liuvv
container_name: hexo_blog_liuvv
ports:
- "4000:4000"
volumes:
- .:/app
# 【关键技巧】这是一个匿名卷,用于隔离 node_modules 目录。作用:防止本地映射覆盖掉镜像里已经安装好的 node_modules,
- /app/node_modules
command: sh -c "hexo server"

# 部署
hexo-deployer:
image: my-hexo-liuvv
volumes:
# 1. 挂载源码,确保部署的是最新内容
- .:/app
# 2. 挂载你的 SSH 密钥,以便能推送到 GitHub
- ~/.ssh:/root/.ssh:ro
# 3. (新增) 将你主机的 Git 配置挂载到容器中
- ~/.gitconfig:/root/.gitconfig:ro
# 4. (推荐) 保留 node_modules 的匿名卷
- /app/node_modules
command: >
sh -c "hexo clean && hexo g -d"

2.5 docker images 清理

1
2
3
4
docker images 有很多 none, 会占用磁盘吗?怎么清理

<none> <none> 6038648f7701 9 minutes ago 428MB
<none> <none> aeed82987cc4 9 minutes ago 428MB
1
docker image prune -f