开发者 Docker 指南:镜像、容器与 Compose
你可能已经听说过 Docker,以及它如何简化你的开发工作流程。但如果你对容器还比较陌生,那些术语和命令可能会让人不知所措。本指南将拨开迷雾,为你提供对 Docker 镜像、容器和 Compose 的实用理解——让你今天就能开始高效使用它们。
Docker 是什么,为什么你应该关注它?
Docker 是一个平台,它将你的应用程序及其依赖项打包成一个称为容器的标准化单元。容器轻量、可移植且彼此隔离,这意味着你可以在自己的笔记本电脑、同事的机器或生产服务器上一致地运行你的应用。
关键好处是什么?“在我机器上能跑”将成为过去。Docker 确保你的代码运行环境在所有地方都完全相同。
镜像 vs. 容器:构建块
在开始之前,你需要理解镜像和容器之间的区别。
- 镜像:一个只读模板,包含你的应用程序代码、运行时、库和依赖项。可以把它看作快照或蓝图。
- 容器:镜像的可运行实例。你可以启动、停止、移动和删除容器。多个容器可以从同一个镜像运行。
简而言之:镜像是菜谱,容器是你用它做出来的菜。
开发者必备的 Docker 命令
以下是你最常使用的命令:
docker pull <image>– 从 Docker Hub 等注册表下载镜像。docker images– 列出所有本地镜像。docker run <image>– 从镜像创建并启动容器。docker ps– 列出正在运行的容器。添加-a可查看所有容器,包括已停止的容器。docker stop <container>– 优雅地停止正在运行的容器。docker rm <container>– 删除已停止的容器。docker rmi <image>– 删除镜像。docker exec -it <container> bash– 在正在运行的容器内打开交互式 shell。
例如,运行一个简单的 Nginx Web 服务器:
docker run -d -p 8080:80 nginx
这会拉取 nginx 镜像(如果本地还没有),以分离模式(-d)启动容器,并将主机上的 8080 端口映射到容器内的 80 端口(-p 8080:80)。
使用 Dockerfile 构建你自己的镜像
要打包你的应用程序,你需要创建一个 Dockerfile——一个包含指令的文本文件。以下是一个 Node.js 应用的简单示例:
# 使用官方 Node.js 运行时作为父镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /usr/src/app
# 复制 package.json 并安装依赖项
COPY package*.json ./
RUN npm install
# 复制其余应用程序代码
COPY . .
# 暴露应用运行的端口
EXPOSE 3000
# 定义运行应用的命令
CMD ["node", "app.js"]
使用以下命令构建镜像:
docker build -t my-node-app .
然后运行它:
docker run -p 3000:3000 my-node-app
使用 Docker Compose 简化多容器应用
现实世界的应用通常需要多个服务:Web 服务器、数据库、缓存等。使用 docker run 逐个管理它们会变得很繁琐。Docker Compose 允许你使用 YAML 文件定义并运行多容器应用。
创建一个 docker-compose.yml 文件:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: example
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
然后使用以下命令启动所有内容:
docker compose up -d
Compose 会为你处理网络、卷和依赖关系。要停止并删除容器、网络和卷,请运行 docker compose down。
开发中使用 Docker 的最佳实践
- 使用 .dockerignore:从构建上下文中排除不必要的文件(如
node_modules),以加快构建速度。 - 利用多阶段构建:通过将构建时依赖项与运行时分离,保持最终镜像小巧。
- 固定版本:指定确切的镜像标签(例如
node:18.16.0-alpine)以确保可复现性。 - 以非 root 用户运行:在 Dockerfile 中创建用户,并使用
USER切换到该用户,以提高安全性。 - 使用卷存储持久化数据:数据库和其他有状态服务应将数据存储在卷中,而不是容器内部。
常见陷阱及如何避免
- 镜像臃肿:从最小基础镜像(如 Alpine)开始,并清理包缓存。
- 端口冲突:确保主机端口尚未被占用。使用
docker ps检查。 - 忽略日志:使用
docker logs <container>调试问题。 - 本地开发不使用 Compose:即使是简单的应用也能从 Compose 的声明式配置中受益。
常见问题
Docker 镜像和容器有什么区别?
镜像是定义应用程序及其环境的只读模板。容器是该镜像的运行实例。你可以从单个镜像创建多个容器。
单容器应用需要 Docker Compose 吗?
不一定。对于简单应用,docker run 就足够了。然而,Compose 使管理环境变量、卷和网络变得更加容易,即使只有一个服务,也能简化后续的扩展。
如何在 Docker 中持久化数据?
使用卷。卷存储在容器文件系统之外,即使容器被删除也会保留。在 Compose 中,定义一个卷并将其挂载到容器中的路径(例如 volumes: - mydata:/var/lib/data)。
准备好优化你的 Docker 工作流程了吗?当你需要分析容器日志时,试试我们的 Nginx 日志分析器,快速解析并可视化日志数据——非常适合调试容器化的 Web 服务器。