Skip to main content

Docker 基础

Docker 用来把应用及其运行时打成 镜像,在本机、CI、生产用同一套文件系统与进程环境跑起来。它和具体编程语言无关:Python、Node、Go、静态站点都可以容器化。

很多仓库的 Dockerfile / Compose 不是你说了算的——先跟现有文件与 CI 构建命令;只有新项目,或团队明确要改造时,再套推荐写法。

容器解决什么

痛点容器怎么帮
「我机器能跑、你机器不行」同一镜像、同一层依赖
系统库 / 原生依赖难装构建阶段装好,运行镜像可精简
运行时版本漂移FROM 钉死基础镜像标签
本地工具链与生产不一致生产以镜像为准,本机可用 Compose 贴近

容器边界是 镜像文件系统 + 进程;语言自带的「虚拟环境 / node_modules」等仍可能出现在镜像内部,只是协作单元变成了镜像,而不是每台机器手装一遍。

核心概念(极简)

概念一句话
镜像(image)只读模板:系统层 + 依赖 + 应用
容器(container)镜像跑起来的进程实例
层(layer)Dockerfile 每步大致对应一层;依赖与源码分开拷,利于缓存
Dockerfile描述如何构建镜像的脚本
仓库(registry)存放/分发镜像(Docker Hub、GHCR、私有仓等)
Compose用 YAML 定义并启动多个容器(应用 + 数据库等)
docker build -t my-app:dev .
docker run --rm -p 8080:8080 my-app:dev
docker compose up --build

-p 主机端口:容器端口 把容器端口映射到本机。容器里的 localhost 只指向该容器自己,访问同 Compose 网络里的其他服务要用服务名(如 db:5432),不要写 localhost

先认现场

标志含义你通常该怎么做
Dockerfile / Dockerfile.*镜像构建入口读注释与 CI 里的 docker build 参数
docker-compose.yml / compose.yaml本地多服务编排docker compose up(以 README 为准)
.dockerignore构建上下文排除项保留对本地依赖目录、.git、缓存的忽略
基础镜像(node: / python: / golang: / nginx: …)运行时选型与仓库技术栈对齐,勿随意换族
仅有 K8s/Helm、无本地 Docker 文档部署在集群侧问清本地是否还需 Compose

通用 Dockerfile 习惯

与语言无关的常见结构:

  1. 选准并钉住基础镜像(含主版本,避免无脑 latest
  2. 先复制依赖清单、再安装依赖、最后复制源码 → 源码变动不致整层依赖重装(缓存友好)
  3. 多阶段构建:构建工具留在 builder,运行镜像只留运行所需
  4. .dockerignore 排除本地依赖目录、VCS、测试缓存,减小上下文、避免脏文件进镜像
  5. 配置走环境变量;密钥不要写进镜像层;默认非 root 运行(以团队规范为准)

通用 .dockerignore 思路(按栈增删):

.git/
**/node_modules/
**/.venv/
**/__pycache__/
**/dist/
**/build/
**/.pytest_cache/
**/.mypy_cache/

最小示例(任意「有依赖清单的应用」)

FROM <runtime>:<version>-slim

WORKDIR /app

# 1) 只拷依赖声明
COPY <lock-or-manifest> ./
RUN <install-prod-deps>

# 2) 再拷源码
COPY . .
CMD ["<start-command>"]

具体 <runtime> / <install-prod-deps> 随语言变化;下面给几种常见写法。

各语言示例(对照)

Node(npm)

FROM node:22-bookworm-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "server.js"]

Python(pip)

FROM python:3.12-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]

Python(uv,多阶段)

与可复现锁文件配合时常用:

FROM python:3.12-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:0.11.32 /uv /uvx /bin/
ENV UV_PYTHON_DOWNLOADS=0
WORKDIR /app

RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --no-dev --no-install-project

COPY . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked --no-dev --no-editable

FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /app /app
ENV PATH="/app/.venv/bin:$PATH"
CMD ["python", "main.py"]

说明:钉 uv 版本;--locked 按提交的锁文件安装;--no-dev 去掉开发依赖;本地 .venv 必须进 .dockerignore

Python 侧的解释器与包管理约定,见知识库「编程语言 → Python」中的多版本 / 项目与包管理;容器实践以本篇为准

Go(多阶段)

FROM golang:1.22-bookworm AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app ./cmd/app

FROM gcr.io/distroless/static-debian12
COPY --from=builder /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]

构建阶段用完整 Go 工具链;运行镜像只留静态二进制。需要 CGO / 动态链接时,运行阶段改用 debian/alpine 等带 libc 的基础镜像。

静态站点 / 反向代理

FROM nginx:1.27-alpine
COPY ./dist /usr/share/nginx/html

前端构建可在 CI 或多阶段的前一阶段完成,最终镜像只保留产物。

Compose:本地多服务

services:
api:
build: .
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: example
volumes:
- pgdata:/var/lib/postgresql/data

volumes:
pgdata:

习惯:

  • 密钥用环境变量 / env_file不要写进镜像层
  • 开发可挂载源码卷;生产镜像一般打进产物,不靠 bind mount
  • 默认 depends_on 只保证「容器已启动」,不保证数据库已可接受连接;需要等就绪时用健康检查 + depends_on.condition(以团队模板为准)

本机工具链 vs 镜像

语言版本管理器 / 本机 SDK → 开发体验
锁文件 / 依赖清单 → 装哪一棵依赖树
Dockerfile / Compose → 如何构建与本地联调
CI → 构建、扫描、推送镜像

生产运行以 镜像标签 为准;本机 SDK 版本应与基础镜像 主版本对齐,避免「本地过、镜像挂」。

常用排错

docker compose ps # 看服务是否在跑
docker compose logs -f api # 跟日志
docker compose exec api sh # 进容器(镜像无 sh 时换 bash)
docker images # 本机镜像
docker system df # 占了多少磁盘

构建失败先看 Dockerfile 哪一步;跑起来连不上库,先确认 Compose 服务名、端口,以及应用是否在等库就绪。

你不能做主时

  1. 不改动正在用的基础镜像族,除非有迁移任务
  2. 本地调试优先:docker compose / README 里的 build 参数
  3. 只想加快安装时,可在 既有 Dockerfile 结构内 换更快安装器,并确认锁文件与缓存仍正确
  4. 业务 hotfix 里夹带「重写 Dockerfile + 换包管理器」风险极高

要点

  1. Docker 是通用运行时封装;先跟仓库现有 Dockerfile / Compose / CI
  2. 钉基础镜像、依赖与源码分层、.dockerignore、配置外置、锁文件与 CI 一致
  3. Compose 管本地依赖服务;密钥不进镜像;容器间用服务名,勿误用 localhost
  4. 镜像标签、锁文件、CI 三者一致,比追求「最新写法」更重要