4、Docker容器化入门:Docker安装与配置、镜像与容器概念、Dockerfile编写、常用命令实战
说实话,Docker 这东西,刚接触时觉得挺玄乎。什么镜像、容器、仓库,一堆新名词。但等你真正用上手,就会发现——它其实就是个「轻量级虚拟机」,只不过启动快得离谱。
我在团队里推 Docker 的时候,最大的阻力不是技术,而是大家觉得「多了一层东西,麻烦」。结果呢?等我把测试环境从手动部署变成一条命令搞定,所有人都真香了。
4.1 Docker 是什么?为什么测试环境需要它?
Docker 是一种容器化技术。它能把你的应用和所有依赖打包在一起,形成一个标准单元。这个单元可以在任何安装了 Docker 的机器上运行,保证行为一致。
你想想看,测试环境最头疼的是什么?「在我机器上是好的啊!」这句话,我听了不下百遍。Docker 就是来解决这个问题的。
和传统虚拟机比,Docker 有几个明显优势:
| 对比项 | 传统虚拟机 | Docker 容器 |
|---|---|---|
| 启动速度 | 分钟级 | 秒级 |
| 资源占用 | GB 级别 | MB 级别 |
| 内核 | 独立内核 | 共享宿主机内核 |
| 隔离性 | 完全隔离 | 进程级隔离 |
| 适用场景 | 需要完整 OS 环境 | 微服务、测试环境、CI/CD |
我个人习惯在测试环境里,每个服务一个容器。数据库、缓存、消息队列、被测应用,全部容器化。这样环境挂了,直接删了重建,比修虚拟机快多了。
4.2 Docker 安装与配置
安装 Docker 其实不复杂。我以 Ubuntu 为例,其他系统大同小异。
4.2.1 安装步骤
- 卸载旧版本(如果有的话)
sudo apt-get remove docker docker-engine docker.io containerd runc
- 安装依赖
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
- 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- 设置稳定版仓库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.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 docker-ce docker-ce-cli containerd.io
- 验证安装
sudo docker run hello-world
看到 Hello from Docker! 就说明安装成功了。
sudo usermod -aG docker $USER记得退出重新登录才生效。
4.2.2 配置镜像加速
国内拉取镜像经常慢得让人抓狂。我曾经等一个镜像等了半小时,最后超时了。后来配置了镜像加速,速度直接起飞。
编辑 /etc/docker/daemon.json:
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
]
}
重启 Docker 生效:
sudo systemctl daemon-reload
sudo systemctl restart docker
4.3 镜像与容器概念
这两个概念是 Docker 的核心。我刚开始也搞混过,后来用一句话就记住了:
镜像是模板,容器是实例。
就像面向对象编程里的类和对象。镜像是类,定义了环境和应用;容器是对象,是运行中的实例。
4.3.1 镜像(Image)
- 只读模板,包含操作系统、依赖、应用代码
- 由多层构成,每层都是只读的
- 可以从 Docker Hub 拉取,也可以自己构建
4.3.2 容器(Container)
- 镜像的运行实例
- 可读可写,可以启动、停止、删除
- 每个容器相互隔离
4.4 Dockerfile 编写
Dockerfile 就是构建镜像的「配方」。写得好不好,直接影响镜像大小和构建速度。
4.4.1 基本结构
一个最简单的 Dockerfile 长这样:
# 指定基础镜像
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY requirements.txt .
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 8000
# 启动命令
CMD ["python", "app.py"]
4.4.2 编写原则
我总结了几条经验:
- 选择合适的基础镜像:alpine 版本最小,slim 版本次之,full 版本最大。测试环境用 slim 就够了。
- 减少层数:每个 RUN、COPY、ADD 都会增加一层。能用
&&合并的就合并。 - 利用缓存:把不常变动的指令放在前面,比如安装依赖。这样代码改了,依赖不用重新安装。
- 清理临时文件:安装完依赖后,清理 apt 缓存、pip 缓存,能大幅减小镜像体积。
4.4.3 多阶段构建
对于编译型语言(Go、Java、C++),多阶段构建是神器。它能把编译环境和运行环境分开,最终镜像只保留运行所需的最小文件。
# 第一阶段:编译
FROM golang:1.18 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# 第二阶段:运行
FROM alpine:3.15
WORKDIR /app
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]
最终镜像只有十几 MB,而不是几百 MB。
4.5 常用命令实战
命令不用死记硬背,用多了自然就记住了。我列几个最常用的:
4.5.1 镜像管理
| 命令 | 说明 | 示例 |
|---|---|---|
docker images |
列出本地镜像 | docker images |
docker pull |
拉取镜像 | docker pull nginx:latest |
docker rmi |
删除镜像 | docker rmi nginx |
docker build |
构建镜像 | docker build -t myapp:1.0 . |
4.5.2 容器管理
| 命令 | 说明 | 示例 |
|---|---|---|
docker run |
创建并启动容器 | docker run -d -p 8080:80 nginx |
docker ps |
列出运行中的容器 | docker ps -a(列出所有) |
docker stop |
停止容器 | docker stop container_id |
docker rm |
删除容器 | docker rm container_id |
docker logs |
查看日志 | docker logs -f container_id |
docker exec |
进入容器 | docker exec -it container_id bash |
4.5.3 实战场景:启动一个 Nginx 服务
我们来跑一个完整的例子:
# 拉取 Nginx 镜像
docker pull nginx:alpine
# 启动容器,映射端口
docker run -d --name my-nginx -p 8080:80 nginx:alpine
# 查看容器状态
docker ps
# 访问测试
curl http://localhost:8080
# 查看日志
docker logs my-nginx
# 进入容器
docker exec -it my-nginx sh
# 停止并删除
docker stop my-nginx
docker rm my-nginx
整个过程不到 10 秒。这就是 Docker 的魅力。
4.6 知识体系总览
下面这张图,把 Docker 的核心概念和关系串起来了:
4.7 本章小结
Docker 入门其实不难。记住几个关键点:
- 安装配置:装好 Docker,配好镜像加速,这是第一步
- 理解概念:镜像 vs 容器,搞清楚区别
- 写好 Dockerfile:注意层数、缓存、多阶段构建
- 掌握常用命令:run、ps、stop、rm、logs、exec,够用了