开发者Docker指南:镜像、容器与Compose
你编写的代码在你的机器上运行正常,但当队友尝试运行时,他们遇到了缺失依赖、版本冲突或晦涩的错误。Docker通过将应用程序及其环境打包成一个可移植的单元来解决这个问题。在本指南中,你将学习Docker的基础知识:镜像、容器和Compose,并通过实际步骤将一个简单的Web应用容器化。
什么是Docker?
Docker是一个用于在容器中构建、运行和共享应用程序的平台。容器是一个轻量级、独立的可执行包,包含运行软件所需的一切:代码、运行时、系统工具、库和设置。容器将应用程序彼此隔离,并与主机系统隔离,确保开发、测试和生产环境的一致性。
镜像 vs 容器:蓝图与运行实例
镜像是一个只读模板,定义了容器。它类似于面向对象编程中的类。容器是镜像的可运行实例,类似于对象。你可以从同一个镜像创建多个容器。
镜像通过Dockerfile构建,这是一个包含指令的文本文件。容器通过docker run启动。
主要区别
| 镜像 | 容器 |
|---|---|
| 只读模板 | 可运行实例 |
通过docker build构建 | 通过docker run启动 |
| 存储在注册表中(例如Docker Hub) | 在主机上运行 |
| 分层文件系统 | 顶部可写层 |
构建你的第一个镜像
让我们容器化一个简单的Node.js应用。创建一个名为Dockerfile的文件:
# 使用官方Node.js运行时作为父镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制package.json并安装依赖
COPY package*.json ./
RUN npm install
# 复制应用程序的其余部分
COPY . .
# 暴露应用运行的端口
EXPOSE 3000
# 定义运行应用的命令
CMD ["node", "server.js"]
使用标签构建镜像:
docker build -t my-node-app .
-t标志为镜像命名并打标签。末尾的.指定构建上下文(当前目录)。
运行容器
从你的镜像启动一个容器:
docker run -p 3000:3000 -d --name my-app my-node-app
-p 3000:3000:将主机的3000端口映射到容器的3000端口。-d:以分离模式(后台)运行容器。--name my-app:为容器分配一个名称以便于引用。
使用docker ps检查正在运行的容器。使用docker stop my-app停止容器。
使用卷管理数据
容器是短暂的;当容器被删除时,其中的数据也会丢失。要持久化数据,请使用卷。例如,要持久化数据库数据:
docker run -v my-db-data:/var/lib/mysql -d mysql:8
这将创建一个名为my-db-data的命名卷,它在容器重启和删除后仍然存在。
使用Docker Compose简化多容器应用
实际应用通常需要多个服务:Web服务器、数据库、缓存等。Docker Compose允许你通过一个YAML文件定义和运行多容器应用。
创建一个docker-compose.yml:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
postgres_data:
使用以下命令运行所有内容:
docker compose up -d
Compose构建Web镜像,启动数据库,并将它们连接在共享网络上。depends_on确保数据库在Web服务之前启动。
基本Docker命令
docker ps -a:列出所有容器(包括已停止的)。docker images:列出镜像。docker logs my-app:查看容器日志。docker exec -it my-app sh:在运行中的容器内打开shell。docker compose down:停止并移除Compose文件中定义的容器、网络和卷。
开发最佳实践
- 使用.dockerignore从构建上下文中排除文件(例如node_modules),加快构建速度。
- 利用多阶段构建保持生产镜像小巧。例如,在一个阶段构建应用,只将必要的产物复制到精简的运行时镜像中。
- 固定版本在Dockerfile中(例如使用
node:18-alpine而不是node:latest)以确保可重复性。 - 以非root用户运行以提高安全性。在复制文件后添加
USER node。
常见问题
Docker镜像和容器有什么区别?
镜像是一个只读模板,定义了应用程序及其环境。容器是该镜像的运行实例。你可以从同一个镜像创建多个容器。
如何在Docker中持久化数据?
使用卷。命名卷(例如docker run -v my-vol:/data)存储在容器的文件系统之外,并在容器重启和删除后持久存在。
何时应该使用Docker Compose?
当你的应用程序由多个需要一起运行的服务(例如Web +数据库)组成时,使用Compose。它简化了开发和测试的编排。
准备好容器化你的下一个项目了吗?从编写一个简单的Dockerfile并运行你的第一个容器开始。如需更多开发者工具,请查看TryQuickToolBox的JSON格式化工具,在测试容器化服务时验证API响应。