容器基础(01):Docker 基础——镜像、容器、Dockerfile、容器生命周期
更新时间:2026-09-01。本文是
cloud/docker/Docker 基础第 01 篇,在 Docker 索引下。Docker 是最流行的容器化工具,把应用代码 + 依赖打包成镜像,在任何环境都能一致运行。理解镜像和容器的区别、容器生命周期,才能正确使用 Docker。
本文要回答的问题
- 镜像和容器有什么区别?
- Dockerfile 常用指令有哪些?怎么写高效的 Dockerfile?
- 容器生命周期:create/start/stop/restart/rm?
- docker run 常用选项:端口映射、环境变量、volume?
一、镜像 vs 容器
| 概念 | 含义 | 类比 |
|---|---|---|
| 镜像(Image) | 只读模板,包含应用 + 依赖 + 配置 | 程序安装包 |
| 容器(Container) | 镜像运行实例,每个容器独立隔离 | 运行的程序进程 |
bash
# 查看所有镜像
docker images
# 拉取镜像
docker pull nginx:1.25
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止)
docker ps -a二、Dockerfile 编写
dockerfile
# 基于基础镜像
FROM node:18-alpine
# 维护者信息(可选)
LABEL maintainer="author@example.com"
# 设置工作目录
WORKDIR /app
# 复制代码到镜像
COPY . .
# 安装依赖
RUN npm install --production
# 暴露端口(只是文档,不自动映射)
EXPOSE 3000
# 设置环境变量
ENV NODE_ENV production
# 启动命令
CMD ["node", "index.js"]Dockerfile 指令:
FROM:基础镜像,必须第一行WORKDIR:工作目录,比cd好COPY:复制本地文件到镜像,COPY src destADD:支持解压缩和 URL 下载,尽量用COPYRUN:执行命令,构建镜像时运行EXPOSE:声明暴露端口,不实际绑定ENV:设置环境变量CMD:容器启动命令,只有一个 CMD
三、高效 Dockerfile 技巧
dockerfile
# 1. 层缓存:把不变的层放前面,变化的放后面
# ✅ 好:依赖先安装,代码后复制
FROM node:18-alpine
WORKDIR /app
COPY package.json .
RUN npm install # 依赖不变,缓存命中
COPY . .
CMD ["node", "index.js"]
# ❌ 坏:代码每次变,依赖每次重新安装
COPY . .
RUN npm install
# 2. 多阶段构建
# 第一阶段:构建(node 镜像编译代码)
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.mod go.sum .
RUN go mod download
COPY . .
RUN go build -o app .
# 第二阶段:只放二进制(基础镜像小)
FROM alpine:3.19
COPY --from=builder /app/app /usr/local/bin/app
CMD ["app"]
# 最终镜像只有 alpine + 二进制,比 golang 镜像小很多四、docker run 常用选项
bash
# 后台运行,命名容器
docker run -d --name my-nginx nginx
# 端口映射:主机 80 → 容器 80
docker run -d -p 80:80 nginx
# 多个端口映射
docker run -d -p 80:80 -p 443:443 nginx
# 环境变量
docker run -d -e "NODE_ENV=production" -e "PORT=3000" my-app
# 挂载 volume:主机目录 /data → 容器 /app/data
docker run -d -v /data:/app/data my-app
# 匿名 volume:容器数据持久化
docker run -d -v /var/lib/mysql mysql
# 只读根文件系统
docker run -d --read-only nginx
# 限制 CPU 和内存
docker run -d --cpus=1 --memory=512m my-app
# 交互式运行(进入 bash)
docker run -it --rm ubuntu bash
# --rm:容器退出后自动删除
docker run -it --rm ubuntu bash五、容器生命周期
bash
# 创建容器但不启动
docker create --name my-nginx nginx
# 启动容器
docker start my-nginx
# 停止容器(优雅停止,发送 SIGTERM)
docker stop my-nginx
# 强制杀死容器
docker kill my-nginx
# 重启容器
docker restart my-nginx
# 删除停止的容器
docker rm my-nginx
# 强制删除运行中的容器
docker rm -f my-nginx
# 查看容器日志
docker logs my-nginx
docker logs -f my-nginx # 实时看日志
# 进入容器 shell
docker exec -it my-nginx bash
# 查看容器信息
docker inspect my-nginx六、Docker 核心概念
Docker 架构:
┌─────────┐
│ Client │ docker CLI
└────┬─────┘
│
┌────▼────────────────────────────────┐
│ Docker Daemon (守护进程) │
│ ┌───────────┐ ┌──────────────┐ │
│ │ Images │ │ Containers │ │
│ │ Networks │ │ Volumes │ │
│ └───────────┘ └──────────────┘ │
└────────────────────────────────────┘
│
┌────▼──────────┐
│ Registry │ Docker Hub / 私有 registry
└──────────────┘七、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
| 镜像层太多,镜像太大 | 镜像推送到仓库慢 | 合并 RUN 指令,用多阶段构建 |
| 缓存顺序不对,依赖每次重新安装 | 构建慢 | 把不变层(依赖)放前面 |
| 容器里进程 1 不处理 SIGTERM | docker stop 10 秒后才杀死 | 用 exec 形式 CMD ["node", "app.js"],不用 shell 形式 CMD node app.js |
| 容器退出后数据丢失 | 数据没持久化 | 用 volume 挂载数据目录 |
相关与延伸
下一篇:Docker 镜像存储——分层、overlayfs、镜像优化、存储驱动;容器底层隔离,见 概念层 namespace/cgroup.
一句话总结
Docker 基础:镜像是只读模板,容器是镜像运行实例;Dockerfile 用 FROM 基础镜像,WORKDIR 设置工作目录,COPY 复制代码,RUN 安装依赖,CMD 启动命令;高效 Dockerfile:依赖层放前面利用缓存,多阶段构建得到小镜像;docker run -d -p 80:80 -v /host:/container -e KEY=VAL;容器生命周期:create → start → stop → rm;docker logs 看日志,docker exec 进入容器。