Docker 容器化入门:镜像、容器与仓库
什么是 Docker 与容器化
Docker 是一个开源的容器化平台,允许开发者将应用及其所有依赖打包到一个轻量级、可移植的容器中。容器与虚拟机不同,它们共享宿主机的操作系统内核,启动更快,资源占用更少。容器化解决了“在我机器上能跑”的问题,保证应用在任何环境中的一致性。
核心概念有三个:
- 镜像(Image):一个只读模板,包含了运行应用所需的文件系统、代码、运行时、库和环境变量。
- 容器(Container):镜像的运行实例,可以启动、停止、删除,彼此隔离。
- 仓库(Registry):存储和分发镜像的地方,最著名的是 Docker Hub。
本教程将带你从零开始理解这些核心概念,并通过实际操作完成你的第一个容器化应用。
环境准备
开始前,请根据你的操作系统安装 Docker Desktop(Windows/Mac)或 Docker Engine(Linux)。安装完成后,在终端输入以下命令验证:
docker --version
docker run hello-world
如果成功输出欢迎信息,说明环境已就绪。
Docker 镜像:构建应用的蓝图
什么是镜像
镜像是分层构建的,每一层代表一个指令(如安装软件、复制文件)。这种分层设计让镜像复用和传输变得极为高效。比如,基于同一个 Ubuntu 基础镜像构建的多个应用,只需共享基础层,大大减少磁盘占用。
获取镜像
从仓库拉取镜像使用 docker pull 命令。例如,获取最新的 Nginx 镜像:
docker pull nginx:latest
查看本地已有镜像:
docker images
输出中会显示 REPOSITORY、TAG、IMAGE ID 等信息。
编写 Dockerfile 构建自定义镜像
Dockerfile 是一个文本文档,包含构建镜像的指令。下面是一个简单的 Node.js 应用示例:
# 使用官方 Node.js 基础镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制 package.json 并安装依赖
COPY package*.json ./
RUN npm install
# 复制应用代码
COPY . .
# 声明容器监听的端口
EXPOSE 3000
# 定义启动命令
CMD ["node", "server.js"]
在 Dockerfile 所在目录执行构建命令:
docker build -t my-node-app:1.0 .
-t 指定镜像名称和标签,最后的 . 表示上下文路径。构建过程会逐层缓存,下次构建未更改的层会直接复用,提升速度。
镜像标签管理
标签用于区分镜像版本。如果不指定,默认为 latest。为已有镜像添加新标签:
docker tag my-node-app:1.0 my-node-app:latest
镜像的分享与备份
可将镜像导出为 tar 文件,便于离线传输:
docker save -o my-node-app.tar my-node-app:1.0
从 tar 文件加载镜像:
docker load -i my-node-app.tar
Docker 容器:运行你的应用
容器的生命周期
容器是镜像的运行时实例。通过 docker run 创建并启动容器:
docker run --name my-container -d -p 8080:3000 my-node-app:1.0
参数解释:
--name:给容器命名,便于管理-d:后台运行(守护模式)-p 8080:3000:将宿主机的 8080 端口映射到容器的 3000 端口
管理运行中的容器
常用命令:
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a
# 停止容器
docker stop my-container
# 启动已存在的容器
docker start my-container
# 重启容器
docker restart my-container
# 删除容器(必须先停止)
docker rm my-container
# 强制删除运行中的容器
docker rm -f my-container
进入容器内部调试
当容器在运行时,可以进入其 shell 环境:
docker exec -it my-container sh
对于使用 bash 的镜像,将 sh 替换为 bash。-it 实现了交互式终端。
查看容器日志和资源使用
实时查看日志:
docker logs -f my-container
查看资源占用(CPU、内存):
docker stats
数据持久化:卷和绑定挂载
容器默认是无状态的,删除后数据会丢失。使用卷(Volume)或绑定挂载(Bind mount)解决这个问题。
创建卷并挂载:
docker volume create app-data
docker run -d --name my-container -v app-data:/app/data my-node-app:1.0
绑定挂载直接映射宿主目录(常用于开发环境):
docker run -d -v $(pwd)/src:/app/src my-node-app:1.0
Docker 仓库:分发与协作
公共仓库 Docker Hub
Docker Hub 是官方的公共仓库。推送前需要先登录:
docker login
为镜像打标签,格式为 用户名/仓库名:标签:
docker tag my-node-app:1.0 yourusername/my-node-app:1.0
推送到 Docker Hub:
docker push yourusername/my-node-app:1.0
现在其他人就可以用 docker pull yourusername/my-node-app:1.0 获取你的镜像。
私有仓库搭建
在企业内部,常使用私有仓库如 Docker Registry 或 Harbor。快速启动本地 Registry:
docker run -d -p 5000:5000 --name registry registry:2
打标签时指定本地地址:
docker tag my-node-app:1.0 localhost:5000/my-node-app:1.0
docker push localhost:5000/my-node-app:1.0
从私有仓库拉取:
docker pull localhost:5000/my-node-app:1.0
实践:从零容器化一个 Web 应用
让我们整合以上知识,创建一个简单的静态网站容器。
-
创建项目目录,放入
index.html。mkdir static-site && cd static-site echo "<h1>Hello Docker!</h1>" > index.html -
编写 Dockerfile(使用 Nginx 作为 Web 服务器):
FROM nginx:alpine COPY index.html /usr/share/nginx/html/index.html EXPOSE 80 -
构建镜像:
docker build -t my-static-site . -
运行容器并映射到本地的 8080 端口:
docker run -d -p 8080:80 --name site my-static-site -
打开浏览器访问
http://localhost:8080,即可看到你的页面。 -
清理资源:
docker stop site docker rm site docker rmi my-static-site
常用命令速查表
| 操作 | 命令 |
|---|---|
| 拉取镜像 | docker pull [image]:[tag] |
| 列出镜像 | docker images |
| 删除镜像 | docker rmi [image] |
| 构建镜像 | docker build -t [name]:[tag] . |
| 运行容器 | docker run -d --name [name] -p [host]:[container] [image] |
| 查看运行容器 | docker ps |
| 停止容器 | docker stop [container] |
| 删除容器 | docker rm [container] |
| 执行命令 | docker exec -it [container] [command] |
| 查看日志 | docker logs [container] |
| 登录仓库 | docker login |
| 推送镜像 | docker push [image] |
| 拉取镜像 | docker pull [image] |
最佳实践与故障排除
- 使用 .dockerignore 文件:排除不需要的文件(如 node_modules、.git),减少构建上下文大小。
- 多阶段构建:分离编译环境和运行环境,最终镜像只保留运行时必要内容,极大缩小体积。
- 以非 root 用户运行:在 Dockerfile 中使用
USER指令提升安全性。 - 网络与端口故障:若端口映射无效,检查防火墙或使用
docker port确认映射关系。 - 构建缓存失效:当 Dockerfile 中某一步的上下文发生变化,后续层会重新构建。合理安排顺序,将不易变动的指令(如安装系统依赖)放在前面,利用缓存。
下一步
现在你已经掌握了 Docker 的核心构件:镜像、容器和仓库。接下来可以深入学习 Docker Compose 管理多容器应用,以及 Kubernetes 进行大规模容器编排。容器化之路,从一个命令开始。