Docker 是当今最流行的容器化平台,它通过将应用及其依赖打包到一个轻量级、可移植的容器中,彻底改变了软件的开发、测试与部署方式。无论你是后端开发、运维工程师,还是全栈开发者,掌握 Docker 都已成为一项必备技能。本文将从零开始,带你系统学习 Docker 的核心概念与实战操作。
一、Docker 核心概念
在动手之前,我们需要先理解 Docker 的几个核心概念,这是后续学习的基础。
- 镜像(Image):类似于面向对象中的"类",是一个只读的模板,包含运行应用所需的所有内容(代码、运行时、库、环境变量、配置文件)。
- 容器(Container):类似于"对象",是镜像运行起来的实例。容器是相互隔离的,每个容器都有自己的文件系统、网络和进程空间。
- 仓库(Registry):存放镜像的地方,最知名的是 Docker Hub,你也可以搭建私有仓库。
- Dockerfile:一个文本文件,包含了一条条指令,用于描述如何构建镜像。
简单理解:镜像是蓝图,容器是根据蓝图造出来的房子,仓库是存放蓝图的图书馆,Dockerfile 则是绘制蓝图的说明书。
二、Docker 安装
2.1 Linux 环境安装(以 Ubuntu 为例)
推荐使用官方仓库安装 Docker CE(社区版),这是最稳定的方式。
bash# 更新 apt 包索引并安装依赖
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
# 添加 Docker 官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 设置 Docker 仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker Engine
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 将当前用户加入 docker 组,免 sudo 运行
sudo usermod -aG docker $USER
# 重新登录后生效,或执行 newgrp docker
# 验证安装
docker --version
sudo docker run hello-world
2.2 配置镜像加速
国内拉取 Docker Hub 镜像速度较慢,建议配置镜像加速器。编辑 /etc/docker/daemon.json:
json{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://docker.mirrors.ustc.edu.cn"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
配置完成后重启 Docker 服务:
bashsudo systemctl daemon-reload
sudo systemctl restart docker
三、镜像管理
镜像是 Docker 的基础,掌握镜像的搜索、拉取、查看与构建至关重要。
bash# 搜索镜像
docker search nginx
# 拉取镜像(默认 latest 标签)
docker pull nginx
docker pull nginx:1.25-alpine # 指定版本
# 列出本地镜像
docker images
# 删除镜像
docker rmi nginx:1.25-alpine
docker image prune -f # 清理悬空镜像
# 查看镜像详情
docker inspect nginx
# 给镜像打标签
docker tag nginx:latest myrepo/nginx:v1.0
四、容器操作
容器是镜像的运行实例,下面介绍容器的核心操作命令。
bash# 运行一个容器(前台交互模式)
docker run -it --name my-ubuntu ubuntu:22.04 /bin/bash
# 运行一个后台容器(守护模式)
docker run -d \
--name web-server \
-p 8080:80 \
-v /data/html:/usr/share/nginx/html \
--restart unless-stopped \
nginx:latest
# 参数说明:
# -d 后台运行
# --name 指定容器名称
# -p 端口映射 宿主机端口:容器端口
# -v 数据卷挂载 宿主机路径:容器路径
# --restart 重启策略
# 查看运行中的容器
docker ps
docker ps -a # 查看所有容器(包括已停止)
# 启动 / 停止 / 重启 / 删除容器
docker start web-server
docker stop web-server
docker restart web-server
docker rm web-server # 删除已停止的容器
docker rm -f web-server # 强制删除运行中的容器
# 进入运行中的容器
docker exec -it web-server /bin/bash
# 查看容器日志
docker logs web-server
docker logs -f --tail 100 web-server # 实时跟踪最后100行
# 查看容器资源占用
docker stats
五、Dockerfile 编写
Dockerfile 是构建自定义镜像的核心。下面以构建一个 Node.js 应用镜像为例,讲解常用指令。
dockerfile# 使用官方 Node.js 轻量镜像作为基础
FROM node:20-alpine
# 设置工作目录
WORKDIR /app
# 设置环境变量
ENV NODE_ENV=production
ENV PORT=3000
# 先复制依赖文件,利用缓存层加速构建
COPY package*.json ./
RUN npm install --production
# 再复制源代码
COPY . .
# 声明端口
EXPOSE 3000
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --quiet --tries=1 --spider http://localhost:3000/health || exit 1
# 以非 root 用户运行(安全最佳实践)
USER node
# 启动命令
CMD ["node", "server.js"]
构建并运行该镜像:
bash# 构建镜像,-t 指定名称和标签
docker build -t myapp:1.0 .
# 运行容器
docker run -d --name myapp -p 3000:3000 myapp:1.0
构建优化技巧:把变化频率低的操作(如安装依赖)放在前面,变化频率高的操作(如复制源码)放在后面,这样可以充分利用 Docker 的层缓存,大幅加快重复构建速度。
六、数据卷与持久化
容器内的数据是临时的,容器删除后数据也会丢失。数据卷(Volume)用于实现数据持久化与容器间数据共享。
bash# 创建命名数据卷
docker volume create mydata
# 挂载数据卷运行容器
docker run -d \
--name db \
-v mydata:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.0
# 查看数据卷
docker volume ls
docker volume inspect mydata
# 绑定挂载(挂载宿主机目录)
docker run -d \
--name web \
-p 8080:80 \
-v /home/user/www:/usr/share/nginx/html:ro \
nginx:latest
# :ro 表示只读挂载,容器内无法修改
七、Docker 网络
Docker 提供了多种网络模式,理解网络是进行多容器通信的关键。
| 网络模式 | 说明 | 使用场景 |
|---|---|---|
| bridge | 默认模式,通过网桥连接容器 | 单机多容器通信 |
| host | 容器直接使用宿主机网络 | 对网络性能要求高 |
| none | 无网络 | 安全隔离场景 |
| 自定义网络 | 用户创建的桥接网络,支持 DNS 解析 | 多容器按服务名互访 |
bash# 创建自定义网络
docker network create app-net
# 将容器加入网络(可通过容器名互相访问)
docker run -d --name app-db --network app-net -e MYSQL_ROOT_PASSWORD=secret mysql:8.0
docker run -d --name app-web --network app-net -p 8080:80 nginx:latest
# 在 app-web 容器内可以直接用 app-db 这个名字访问数据库
# 无需关心 IP 地址,Docker 内置 DNS 会自动解析
八、Docker Compose 多容器编排
当应用由多个服务组成时,手动管理容器非常繁琐。Docker Compose 通过一个 YAML 文件定义和运行多容器应用。
yaml# docker-compose.yml - 一个典型的 Web + 数据库架构
version: '3.8'
services:
web:
build: .
container_name: app-web
ports:
- "8080:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
- DB_PORT=3306
depends_on:
- db
restart: unless-stopped
networks:
- app-net
db:
image: mysql:8.0
container_name: app-db
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: appdb
MYSQL_USER: appuser
MYSQL_PASSWORD: apppass
volumes:
- db-data:/var/lib/mysql
restart: unless-stopped
networks:
- app-net
volumes:
db-data:
networks:
app-net:
driver: bridge
使用 Compose 管理应用:
bash# 构建并启动所有服务(后台运行)
docker compose up -d --build
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f web
# 停止并删除容器、网络(保留数据卷)
docker compose down
# 停止并删除所有(包括数据卷)
docker compose down -v
九、生产环境部署最佳实践
9.1 镜像优化
- 使用 Alpine 等轻量基础镜像,减小镜像体积
- 合并 RUN 指令,减少镜像层数
- 使用多阶段构建(multi-stage build),只保留最终运行所需的文件
- 添加
.dockerignore文件,避免不必要的文件进入构建上下文
dockerfile# 多阶段构建示例:编译阶段与运行阶段分离
FROM golang:1.21-alpine AS builder
WORKDIR /build
COPY . .
RUN CGO_ENABLED=0 go build -o myapp -ldflags="-s -w" .
# 最终运行镜像,体积仅几 MB
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY --from=builder /build/myapp /usr/local/bin/
EXPOSE 8080
CMD ["myapp"]
9.2 安全加固
- 以非 root 用户运行容器
- 限制容器资源(CPU、内存),防止单容器耗尽宿主机资源
- 使用只读文件系统
--read-only - 定期扫描镜像漏洞,及时更新基础镜像
bashdocker run -d \
--name app \
--read-only \
--tmpfs /tmp \
--memory=512m \
--cpus=1.0 \
--user 1000:1000 \
myapp:1.0
十、常用命令速查表
| 命令 | 作用 |
|---|---|
| docker build | 构建镜像 |
| docker run | 创建并启动容器 |
| docker ps | 查看运行中的容器 |
| docker exec | 在容器中执行命令 |
| docker logs | 查看容器日志 |
| docker stats | 查看资源占用 |
| docker system prune | 清理无用资源 |
| docker compose up | 启动编排服务 |
总结
本文从 Docker 的核心概念出发,系统讲解了安装配置、镜像管理、容器操作、Dockerfile 编写、数据卷、网络以及 Docker Compose 多容器编排,最后给出了生产环境的最佳实践。Docker 的学习曲线相对平缓,但要真正用好它,关键在于理解镜像分层、网络模型和持久化机制,并在实际项目中不断实践。
建议你按照本文的步骤动手操作一遍,从运行第一个 hello-world 容器开始,逐步构建自己的应用镜像。当你能熟练使用 Docker Compose 编排多服务应用时,就已经迈入了容器化部署的大门。后续可以进一步学习 Kubernetes,进入云原生的更广阔世界。