开发者Docker指南:镜像、容器与Compose
你是一名开发者,听说过Docker。也许你尝试过,但对镜像、容器和Compose的概念感到模糊。或者你厌倦了“在我机器上能运行”,想要一个一致的环境。本指南将拨开迷雾,让你切实理解Docker的核心组件以及如何有效使用它们。
为什么开发者需要Docker?
Docker解决了环境不一致的问题。无需直接在机器上安装依赖,而是将应用及其依赖打包到一个容器中。容器在任何地方都以相同方式运行:你的笔记本电脑、同事的笔记本电脑以及生产环境。这消除了设置漂移,使入职变得轻而易举。
镜像:蓝图
镜像是一个只读模板。它包含你的应用代码、运行时、库和环境变量。你通过Dockerfile(一个包含指令的文本文件)来构建镜像。
以下是一个Node.js应用的简单Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
每条指令都会创建一个层。层会被缓存,因此当只有代码更改时,重新构建速度很快。镜像存储在Docker Hub或私有仓库等注册表中。
容器:运行实例
容器是镜像的可运行实例。它是隔离的,但共享主机操作系统内核,因此非常轻量。你可以使用docker run启动容器。
docker run -p 3000:3000 -d my-app
这将主机的3000端口映射到容器的3000端口,并以分离模式运行。容器是临时的:除非使用卷,否则删除后更改会丢失。
关键命令:
docker ps– 列出正在运行的容器docker stop <container>– 停止容器docker rm <container>– 删除容器docker images– 列出镜像docker rmi <image>– 删除镜像
Docker Compose:多容器应用
真实应用通常需要多个服务:Web服务器、数据库、缓存。Docker Compose让你通过一个YAML文件定义并运行多容器应用。
以下是一个包含PostgreSQL的Node.js应用的docker-compose.yml:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:15
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
运行docker compose up启动两个服务。Compose处理网络,因此web可以通过服务名访问db。
何时使用Docker Compose与纯Docker
| 场景 | 使用 |
|---|---|
| 单个容器 | docker run |
| 多个服务(应用+数据库) | Docker Compose |
| 生产编排 | Kubernetes, Swarm |
开发者最佳实践
- 使用.dockerignore排除node_modules、.git等,加速构建。
- 多阶段构建以保持最终镜像小巧。
- 固定版本在FROM语句中以确保可重复性。
- 不要以root运行生产容器。
- 使用卷持久化数据,并在开发过程中实现代码热重载。
常见陷阱
端口冲突:如果3000端口被占用,映射到不同的主机端口:-p 3001:3000。
数据丢失:没有卷,删除容器时数据库数据会消失。
构建缓慢:将Dockerfile指令从最少更改到最频繁更改排序,以利用缓存。
常见问题
镜像和容器有什么区别?
镜像是只读模板;容器是该镜像的运行实例。你可以从同一个镜像运行多个容器。
单个服务需要Docker Compose吗?
不需要。Compose在你有多个服务时大放异彩。对于单个容器,docker run更简单。
如何在Docker中持久化数据?
使用卷。在Compose中定义命名卷,或使用docker run的-v挂载主机目录或命名卷。
准备好优化你的Docker工作流程了吗?查看我们的JSON格式化工具,快速验证和格式化像docker-compose.yml或package.json这样的JSON配置文件。