一、先理解两个核心概念

镜像(Image):只读的模板,包含运行环境 + 代码 + 依赖,相当于”安装光盘”。
容器(Container):镜像运行起来的实例,相当于”装好系统的电脑”,可启动、停止、删除。

写代码时:镜像只读,容器可写。容器里的修改不会影响镜像,想保留数据就要用数据卷。

二、最常用的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 拉取镜像
docker pull nginx:alpine

# 查看
docker images # 本地镜像列表
docker ps # 运行中的容器
docker ps -a # 所有容器(含已停止)

# 运行容器:-d 后台、-p 端口映射、--name 命名
docker run -d --name web -p 8080:80 nginx:alpine

# 进入容器 / 查看日志
docker exec -it web sh
docker logs -f web

# 停止/启动/删除
docker stop web
docker start web
docker rm web # 删除容器
docker rmi nginx:alpine # 删除镜像

# 清理
docker system prune -f # 清理停止的容器、悬空镜像等

三、Dockerfile:把项目变成镜像

以一个 Node.js 项目为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 基础镜像
FROM node:20-alpine

# 设置工作目录
WORKDIR /app

# 先复制 package.json,利用 Docker 分层缓存
COPY package*.json ./
RUN npm install --registry=https://registry.npmmirror.com

# 再复制源码(依赖层缓存不失效,改代码不用重装依赖)
COPY . .

# 暴露端口
EXPOSE 3000

# 启动命令
CMD ["node", "server.js"]

构建并运行:

1
2
docker build -t my-app:1.0 .
docker run -d --name my-app -p 3000:3000 my-app:1.0

分层缓存是性能关键:把”变化少的指令放前面、变化多的放后面”,改代码时 npm install 层直接命中缓存,构建秒级完成。

四、数据卷:容器里数据不丢

容器删除后,里面的数据(数据库、上传文件)会一起消失。用数据卷持久化:

1
2
3
4
5
# 具名卷:数据由 Docker 管理
docker run -d --name mysql8 -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8

# 挂载宿主机目录:适合直接看文件
docker run -d --name nginx -v /Users/me/www:/usr/share/nginx/html -p 8080:80 nginx

修改宿主机目录文件,容器里立即生效,开发时非常方便。

五、docker-compose:一键起整套服务

多个容器(如 Web + MySQL + Redis)用 docker-compose.yml 统一编排:

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
version: "3.8"

services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- mysql
- redis
environment:
- DB_HOST=mysql

mysql:
image: mysql:8
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=myapp
volumes:
- mysql-data:/var/lib/mysql

redis:
image: redis:7-alpine

volumes:
mysql-data:
1
2
3
docker compose up -d        # 后台启动整套
docker compose logs -f web # 看某个服务日志
docker compose down # 停止并删除

容器之间用服务名(mysql、redis)互相访问,Docker 内置 DNS 会自动解析。

六、常见坑

  1. 时区:容器默认 UTC 时间,Dockerfile 里加 ENV TZ=Asia/Shanghai,或用 -e TZ=Asia/Shanghai;
  2. 镜像源慢:配置 registry mirror(国内环境用阿里云/腾讯云加速器);
  3. latest 标签坑:latest 会变,生产环境务必用固定版本号(如 node:20.11.0-alpine);
  4. 容器内访问宿主机:macOS 用 host.docker.internal 代替 localhost;
  5. 日志暴涨:限制日志大小:--log-opt max-size=10m --log-opt max-file=3。

总结

Docker 的上手路线:跑通 docker run → 学会写 Dockerfile → 用数据卷保数据 → 用 compose 编排多服务。容器化带来的环境一致性,是”在我机器上是好的”这类问题的最优解。