2、Docker基础:Docker安装、镜像与容器、Dockerfile编写、Docker Compose入门
聊到云原生开发环境,Docker 绝对是绕不开的第一道门槛。我刚开始接触容器化的时候,其实挺懵的——这东西到底解决了什么问题?说白了,Docker 就是让你的应用「走到哪都能跑」。你写好的代码,带上环境一起打包,丢到任何一台有 Docker 的机器上,一键启动,完事。
嗯,咱们这一章就把 Docker 的基础打扎实。从安装开始,到镜像和容器的操作,再到 Dockerfile 的编写,最后用 Docker Compose 把多个服务串起来。我保证,学完这一章,你就能自己搭一套完整的容器化开发环境了。
2.1 Docker 安装:别踩这些坑
Docker 的安装其实不复杂,但不同系统有些小差异。我个人习惯用官方脚本一键安装,省心。
Linux(以 Ubuntu 为例):
# 卸载旧版本
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
macOS / Windows: 直接去 Docker 官网下载 Docker Desktop 就行。安装完记得把 Docker 加入开机自启,省得每次手动启动。
安装完成后,建议把当前用户加入 docker 组,这样就不用每次敲 sudo 了:
sudo usermod -aG docker $USER
newgrp docker
2.2 镜像与容器:理解核心概念
镜像和容器,这两个概念你得分清楚。我打个比方:镜像就像是一个「类」,定义了应用运行所需的一切——代码、运行时、库、环境变量、配置文件。而容器就是「实例」,是镜像跑起来之后的一个独立进程。
你想想看,一个镜像可以启动多个容器,每个容器之间互相隔离,互不影响。这在微服务架构里太重要了。
2.2.1 常用镜像操作
# 拉取镜像
docker pull nginx:latest
# 查看本地镜像
docker images
# 删除镜像
docker rmi nginx:latest
# 搜索镜像
docker search nginx
latest。为什么?因为 latest 会随着时间变化,你今天拉的和明天拉的可能是不同版本,容易出问题。我在项目中吃过这个亏,后来就养成了指定版本的习惯。
2.2.2 容器生命周期管理
# 创建并启动容器
docker run -d --name my-nginx -p 8080:80 nginx:1.21
# 查看运行中的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a
# 停止容器
docker stop my-nginx
# 启动已停止的容器
docker start my-nginx
# 进入容器内部
docker exec -it my-nginx /bin/bash
# 查看容器日志
docker logs -f my-nginx
# 删除容器
docker rm my-nginx
这里有个细节:-d 表示后台运行,-p 8080:80 是把宿主机的 8080 端口映射到容器的 80 端口。你访问 http://localhost:8080 就能看到 Nginx 的欢迎页了。
2.3 Dockerfile 编写:从零构建镜像
Dockerfile 就是构建镜像的「配方」。你写清楚每一步要做什么,Docker 就会按照你的指令一层层构建出镜像。我刚开始写 Dockerfile 时,总想着一个镜像搞定所有事,结果镜像体积大得吓人。后来才明白,分层构建、减少层数才是王道。
来看一个 Node.js 应用的 Dockerfile 示例:
# 1. 指定基础镜像
FROM node:18-alpine
# 2. 设置工作目录
WORKDIR /app
# 3. 复制 package.json 和 package-lock.json
COPY package*.json ./
# 4. 安装依赖
RUN npm install --production
# 5. 复制源代码
COPY . .
# 6. 暴露端口
EXPOSE 3000
# 7. 启动命令
CMD ["node", "app.js"]
- FROM: 尽量选择 Alpine 版本的基础镜像,体积小、安全漏洞少。我对比过,node:18 有 900MB,而 node:18-alpine 只有 120MB。
- COPY 的顺序: 把不常变动的文件(如 package.json)放在前面,利用 Docker 的缓存机制。这样你改代码时,不用重新安装依赖,构建速度能快很多。
- RUN 命令合并: 多个 RUN 命令可以用
&&连接,减少镜像层数。比如RUN apt-get update && apt-get install -y curl。
构建镜像的命令也很简单:
docker build -t my-node-app:1.0 .
这里的 . 表示 Dockerfile 所在的目录,也就是构建上下文。注意,. 目录下的所有文件都会被发送到 Docker 守护进程,所以记得在项目根目录加个 .dockerignore 文件,排除 node_modules、.git 等不需要的文件。
2.4 Docker Compose 入门:多容器编排
单容器好办,但实际项目中往往是多个服务一起跑——前端、后端、数据库、缓存……一个个手动启动太累了。这时候 Docker Compose 就派上用场了。
Docker Compose 通过一个 docker-compose.yml 文件,定义所有服务的配置,然后一条命令全部启动。我习惯把 Compose 文件放在项目根目录,方便团队协作。
来看一个 Web 应用 + Redis 缓存的例子:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- redis
environment:
- REDIS_HOST=redis
- REDIS_PORT=6379
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
redis-data:
- depends_on: 控制服务启动顺序。但注意,它只保证容器启动顺序,不保证服务就绪。如果 Redis 启动慢,你的 Web 应用可能会连不上。我一般会在应用代码里加个重试机制。
- volumes: 持久化数据。比如 Redis 的数据,如果不挂载卷,容器重启后数据就丢了。这在开发环境还好,生产环境绝对不能这么干。
- environment: 环境变量。敏感信息(如密码)建议用
.env文件管理,别硬编码在 Compose 文件里。
启动和停止服务:
# 启动所有服务(后台运行)
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
# 停止并删除容器
docker-compose down
# 重新构建并启动
docker-compose up -d --build
docker-compose down 时,忘了加 -v 参数,结果把数据卷也删了。如果你只是想停服务,保留数据,用 docker-compose stop 更安全。只有确定要清理所有数据时,才用 docker-compose down -v。
小结
这一章的内容,说白了就是 Docker 的「三板斧」:安装、镜像容器、Dockerfile、Compose。你把这四个点吃透了,云原生开发环境的基础就算打牢了。
我个人建议,学完理论后,马上动手实践。找个简单的项目(比如一个 Node.js 或 Python 的 Web 应用),自己写 Dockerfile,再用 Compose 把数据库和缓存串起来。踩几个坑,印象才深刻。
下一章,我们会深入 Kubernetes,看看容器编排的「王者」是怎么玩的。到时候你会发现,Docker 的基础打得越扎实,学 K8s 就越轻松。
📌 本章核心命令速查表:
| 操作 | 命令 |
|---|---|
| 拉取镜像 | docker pull <镜像名>:<标签> |
| 运行容器 | docker run -d -p 宿主机端口:容器端口 --name 容器名 镜像名 |
| 进入容器 | docker exec -it 容器名 /bin/bash |
| 构建镜像 | docker build -t 镜像名:标签 . |
| 启动 Compose | docker-compose up -d |
| 停止 Compose | docker-compose down |
好了,这一章就到这里。记住,动手比看十遍都管用。去装个 Docker,跑几个容器试试吧!