容器化入门:Docker基础与实操
Docker简介
在进行软件开发或评测时,经常会遇到这样的情况:一个项目 “在我电脑上能正常运行”,可测试、运维人员部署到服务器后,却频频出现环境不一致、依赖缺失、配置冲突等问题,导致无法复现出想要的结果。Docker 作为云原生时代不可或缺的基础设施,重构了现代软件的开发、交付与部署范式,彻底解决了“环境不一致”这一长期困扰开发者和运维人员的痛点。
Docker 是一款开源的应用容器引擎,诞生于 2013 年,最初由 dotCloud 公司(后更名为 Docker Inc)研发并开源,基于 Linux 内核的底层技术实现,如今已跨平台支持 Windows、macOS 等主流操作系统。
通俗来说,Docker 就像一个 “应用打包箱”:它可以将你的应用代码、运行环境、依赖库、配置文件等所有运行所需的内容,全部打包到一个标准化的 “容器” 中。这个容器具备极强的可移植性,无论你是在本地笔记本、测试服务器,还是公有云、私有云的主机上,都能实现一次构建,到处运行,彻底抹平2不同环境之间的差异,让软件交付不再受限于具体的操作系统和硬件配置。
Docker 与虚拟机的区别
在使用 Docker 时,我们往往需要拉取操作系统的镜像(例如 Ubuntu 系统),很多新手这时会产生疑问:连操作系统的镜像都要拉取,这与虚拟机的区别在哪里?
事实上,Docker 拉取的系统镜像并不包含系统内核。从技术本质来看,Docker 实现的是操作系统级虚拟化,区别于传统的硬件级虚拟机技术。虚拟机需要虚拟出完整的操作系统内核、硬件资源(CPU、内存、磁盘等),再在其上安装应用;而 Docker 直接共享宿主机的操作系统内核,仅为应用隔离出独立的运行空间,这也是它极致轻量、高效的核心原因。
相比于虚拟机,Docker 的优势十分显著:
- 启动速度:Docker 秒级启动,虚拟机则需数分钟启动
- 资源占用:单个容器仅占用 MB 级体积,虚拟机通常需 GB 级资源
- 跨平台兼容性:Docker 跨平台适配更灵活,虚拟机受虚拟化平台限制
- 性能表现:Docker 性能与宿主机原生性能几乎一致,虚拟机存在一定性能损耗
Docker 镜像的“一次构建,到处运行”特性更是新手需重点掌握的核心。很多新手每换一台机器运行,都重新构建 Docker 镜像,反复拉取软件镜像耗费大量时间,这完全不必要。构建好的镜像可推送到 Docker Hub 或其他镜像仓库,也可打包为压缩包,在其他机器直接下载运行,大幅提升交付效率。
什么是云原生
云原生(Cloud Native)是云原生计算基金会(CNCF)定义的一套架构理念、技术栈与工程实践体系,核心是让应用从设计之初就适配公有云、私有云、混合云等动态环境,充分利用云的弹性、分布式与自动化能力,而非简单将传统应用“搬上云”。
云原生以容器化(如 Docker)、微服务、Kubernetes 编排、服务网格、不可变基础设施、声明式 API 为核心技术,配合 DevOps 与 CI/CD 流程,实现应用快速迭代、弹性伸缩、故障自愈与高效运维,最终让系统更敏捷、可靠、易扩展,是现代云架构下应用开发与部署的主流模式。
Docker 的三大核心概念
1. 镜像(Image):容器的“标准化模板”
Docker 镜像是一个只读的模板文件,包含了应用运行所需的代码、运行环境、依赖库、环境变量、配置文件等所有内容,是创建 Docker 容器的基础。
镜像具备分层存储特性,基于联合文件系统(UnionFS)实现,一个镜像可由多个只读层叠加而成。例如构建 Java 应用镜像,可基于 Ubuntu 基础镜像,叠加 JDK 环境层,再叠加 Spring Boot 应用层。
分层存储的核心优势是层复用:多个镜像可共享同一基础层,大幅节省磁盘空间;同时镜像推送、拉取时仅需传输变更的层,极大提升传输和存储效率。
2. 容器(Container):镜像的运行实例
容器是镜像运行时的实体,是基于镜像创建的、独立的可读写运行环境。若将镜比作“类”,容器就是类的“实例对象”。
每个容器都拥有独立的文件系统、网络空间、进程空间,容器与容器之间、容器与宿主机之间相互隔离,互不干扰。容器的生命周期与运行的应用绑定——应用启动则容器运行,应用退出则容器停止。
默认情况下,容器内的写入操作仅在容器运行时有效,容器删除后写入的数据会随之丢失。因此生产环境中通常通过**数据卷(Volume)**实现数据的持久化存储,确保关键数据不随容器销毁而丢失。
3. 仓库(Repository):镜像的托管与分发中心
Docker 仓库是集中存储、管理、分发 Docker 镜像的平台,相当于代码领域的 GitHub/GitLab。开发者构建好镜像后,可推送到仓库中;其他环境、人员只需从仓库拉取镜像,就能直接运行对应应用,无需重复构建,实现镜像的标准化分发。
仓库分为公共仓库和私有仓库两类:
- 公共仓库:最主流的是 Docker 官方的 Docker Hub,包含海量官方镜像(如 Ubuntu、MySQL、Redis、Nginx、Python 等),开发者可直接拉取使用,无需从零构建
- 私有仓库:企业内部通常搭建私有仓库(如 Harbor),用于存储企业内部业务镜像,保障数据安全、提升传输效率
Docker 安装
Docker 的安装流程因操作系统不同略有差异,以下是主流平台的安装方式概述:
Windows 系统
- 开启 Windows 虚拟化功能(Hyper-V 或 WSL2)
- 下载 Docker Desktop 安装包,双击运行并完成安装
- 启动 Docker Desktop,等待服务初始化完成即可使用
macOS 系统
- 下载 Docker Desktop for Mac 安装包
- 将 Docker 应用拖入应用文件夹,启动后完成初始化配置
Linux 系统(以 Ubuntu 为例)
- 更新系统包索引:
sudo apt update && sudo apt upgrade -y - 安装依赖包:
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y - 添加 Docker 官方 GPG 密钥:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg - 添加 Docker 软件源:
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 update && sudo apt install docker-ce docker-ce-cli containerd.io -y - 启动 Docker 服务并设置开机自启:
sudo systemctl start docker sudo systemctl enable docker - 验证安装是否成功:
docker --version
Dockerfile:镜像构建的自动化脚本
Dockerfile 是用于自动化构建 Docker 镜像的文本文件,包含了一系列指令和参数,用于定义镜像的构建步骤。通过编写 Dockerfile,我们可以标准化镜像构建流程,确保镜像的可复现性和可维护性。
常用 Dockerfile 指令
| 指令 | 作用 | 示例 |
|---|---|---|
FROM |
指定基础镜像(必须为第一条指令) | FROM ubuntu:22.04 |
RUN |
执行命令(如安装依赖、编译代码等) | RUN apt update && apt install -y nginx |
COPY |
复制本地文件/目录到镜像中 | COPY ./app /app |
ADD |
复制文件/目录(支持解压压缩包、下载网络文件) | ADD ./app.tar.gz /app |
WORKDIR |
设置工作目录 | WORKDIR /app |
EXPOSE |
声明容器暴露的端口 | EXPOSE 8080 |
ENV |
设置环境变量 | ENV APP_ENV=production |
CMD |
容器启动时执行的命令(仅可写一条,多条会被最后一条覆盖) | CMD ["nginx", "-g", "daemon off;"] |
ENTRYPOINT |
容器入口命令(可与 CMD 配合,CMD 作为入口参数) | ENTRYPOINT ["python", "app.py"] |
构建镜像示例
以构建一个简单的 Nginx 镜像为例,步骤如下:
- 创建 Dockerfile 文件:
# 基于官方 Nginx 镜像 FROM nginx:latest # 复制自定义配置文件 COPY ./nginx.conf /etc/nginx/conf.d/default.conf # 暴露 80 端口 EXPOSE 80 # 启动 Nginx 服务 CMD ["nginx", "-g", "daemon off;"] - 执行构建命令:
其中docker build -t my-nginx:latest .-t用于指定镜像名称和标签(格式:名称:标签),.表示 Dockerfile 所在目录。
docker run:运行单个容器的核心命令
docker run 是创建并启动容器的核心命令,通过参数控制容器的运行模式、网络、存储、资源等配置,命令格式为:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
该命令每次仅能启动一个容器,所有配置均通过命令行参数传入,适合快速测试、调试单个应用,但在多容器应用场景下,配置繁琐且难以维护。
基础示例
docker run -d \
--name my-app \
-p 8080:80 \
-e DB_HOST=localhost \
-v ./data:/app/data \
--network my-net \
my-image:latest
常用参数详解
一、运行模式
| 参数 | 说明 | 示例 |
|---|---|---|
-d / --detach |
后台运行(守护进程),返回容器 ID | docker run -d nginx |
-it |
交互模式(-i 保持输入打开 + -t 分配伪终端),用于进入容器操作 |
docker run -it ubuntu bash |
--rm |
容器退出后自动删除(适合一次性任务) | docker run --rm -it ubuntu |
--name |
指定容器名称(默认随机生成) | docker run --name my-nginx nginx |
二、网络配置
| 参数 | 说明 | 示例 |
|---|---|---|
-p / --publish |
指定端口映射(主机端口:容器端口),支持绑定指定地址 | -p 8080:80、-p 127.0.0.1:8080:80 |
-P / --publish-all |
随机映射容器暴露的所有端口 | docker run -P nginx |
--network |
指定容器网络(bridge/host/none/自定义网络) | --network my-net |
--add-host |
自定义容器 hosts 映射 | --add-host host.docker.internal:host-gateway |
--dns |
指定容器 DNS 服务器 | --dns 8.8.8.8 |
三、存储与数据持久化
| 参数 | 说明 | 示例 |
|---|---|---|
-v / --volume |
挂载主机目录/卷到容器(格式:主机路径:容器路径[:权限]) | -v /host/data:/container/data:ro(ro 表示只读) |
--mount |
更灵活的挂载方式(推荐),支持多种挂载类型 | --mount type=bind,src=/host,dst=/container |
--tmpfs |
挂载内存临时文件系统(数据不持久化,容器停止后丢失) | --tmpfs /tmp |
--read-only |
将容器根文件系统设为只读(提升安全性) | docker run --read-only nginx |
四、环境变量
| 参数 | 说明 | 示例 |
|---|---|---|
-e / --env |
设置单个环境变量 | -e MYSQL_ROOT_PASSWORD=123456 |
--env-file |
从文件加载环境变量(适合多环境变量配置) | --env-file ./.env |
五、资源限制
| 参数 | 说明 | 示例 |
|---|---|---|
-m / --memory |
限制容器内存使用上限 | -m 512m(512MB)、-m 2g(2GB) |
--cpus |
限制容器使用的 CPU 核心数 | --cpus 1.5(1.5 核) |
--ulimit |
限制系统资源(如最大打开文件数) | --ulimit nofile=65535:65535 |
六、其他常用配置
| 参数 | 说明 | 示例 |
|---|---|---|
-h / --hostname |
设置容器主机名 | -h my-container |
-w / --workdir |
指定容器工作目录 | -w /app |
--user |
指定容器运行用户(UID 或用户名) | --user 1000、--user nginx |
--privileged |
授予容器特权模式(允许访问主机设备) | docker run --privileged ubuntu |
--entrypoint |
覆盖镜像默认入口命令 | --entrypoint /bin/sh |
命令缺点
docker run 仅支持单容器运行,参数过多时难以维护且无法版本控制;多容器应用需手动管理服务依赖、网络连接等,团队协作效率低,因此实际生产中较少单独使用。
Docker Compose:多容器应用编排工具
Docker Compose 是用于管理多容器应用的工具,通过 docker-compose.yml 配置文件定义多个服务的依赖关系、网络、存储等,一条命令即可启动或停止整个应用栈,完美解决了 docker run 在多容器场景下的痛点。
核心配置文件(docker-compose.yml)
Compose 采用 YAML 格式编写配置,核心包含 version、services、volumes 等部分,示例如下:
# 指定 Compose 版本
version: '3.8'
# 定义服务
services:
# 应用服务
app:
# 基于本地镜像
image: my-app:latest
# 端口映射
ports:
- "8080:80"
# 环境变量
environment:
- DB_HOST=db
- REDIS_HOST=redis
# 数据卷挂载
volumes:
- ./app-data:/app/data
# 依赖服务(启动顺序:db、redis → app)
depends_on:
- db
- redis
# 自定义网络
networks:
- app-net
# 数据库服务
db:
image: postgres:16
environment:
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=app_db
# 数据卷持久化
volumes:
- pg-data:/var/lib/postgresql/data
networks:
- app-net
# 缓存服务
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
networks:
- app-net
# 定义数据卷
volumes:
pg-data:
redis-data:
# 定义自定义网络
networks:
app-net:
常用 Compose 命令
# 构建所有服务的镜像(只构建,不启动)
docker compose build
# 构建并立即启动所有服务(最常用,开发必备)
docker compose up -d --build
# 只构建某个服务,不构建其他
docker compose build app
# 不使用缓存,强制重新构建(解决缓存导致构建不更新的问题)
docker compose build --no-cache
# 启动所有服务(-d 表示后台运行)
docker compose up -d
# 停止并清理容器(保留数据卷)
docker compose down
# 停止并清理容器+数据卷
docker compose down -v
# 查看所有服务日志(-f 实时跟踪)
docker compose logs -f
# 重启指定服务
docker compose restart app
# 查看服务状态
docker compose ps
Docker run 与 Docker Compose 对比
| 维度 | docker run | docker compose |
|---|---|---|
| 容器数量 | 单个 | 多个 |
| 配置方式 | 命令行参数 | YAML 配置文件 |
| 可维护性 | 差,参数繁琐 | 好,可纳入 Git 版本控制 |
| 服务依赖 | 手动管理 | 自动处理(depends_on) |
| 网络配置 | 手动创建 | 自动创建共享网络 |
| 适用场景 | 快速测试、调试单个容器 | 开发环境、完整多容器应用部署 |
适用场景
- docker run:临时运行工具、快速验证镜像、单容器调试
- docker compose:任何涉及多个服务的项目(web + db + cache 等)
实际项目中几乎都用 docker compose,因为配置可复用、可共享、易维护。
常用 Docker 命令实操汇总
结合实际使用场景,这里整理了高频 Docker 命令,覆盖镜像管理、容器操作、数据持久化与系统清理,是日常开发/运维的“必备工具箱”。
一、镜像管理:构建、拉取、推送与打包
镜像作为容器的基础,是容器化的核心载体,以下是全流程操作命令:
1. 查看本地镜像
# 列出所有本地镜像(含镜像ID、仓库、标签、大小)
docker images
# 只显示镜像ID(适合脚本批量操作)
docker images -q
2. 搜索远程镜像(Docker Hub)
# 搜索指定名称的镜像(如 MySQL)
docker search mysql
3. 拉取远程镜像
# 拉取最新版镜像(等价于 mysql:latest)
docker pull mysql
# 拉取指定版本镜像(如 MySQL 8.0)
docker pull mysql:8.0
4. 构建本地镜像(通过 Dockerfile)
# 进入 Dockerfile 所在目录
cd /path/to/dockerfile/dir
# 构建镜像:-t 指定名称:标签,. 表示当前目录为构建上下文
docker build -t my-app:1.0 .
# 构建时指定镜像标签(多版本管理)
docker build -t my-app:latest -t my-app:1.0 .
5. 标记镜像(打标签/重命名)
# 格式:docker tag 原镜像:原标签 新镜像:新标签
docker tag my-app:1.0 my-registry.com/my-team/my-app:1.0
6. 推送镜像到远程仓库
# 登录私有仓库(Docker Hub 无需替换地址)
docker login my-registry.com
# 推送标记好的镜像
docker push my-registry.com/my-team/my-app:1.0
# 退出登录
docker logout my-registry.com
7. 打包/导出镜像(无网络环境传输必备)
# 打包为普通 tar 包
docker save -o my-app.tar my-app:1.0
# 打包并压缩为 gz 包(体积更小,推荐)
docker save my-app:1.0 | gzip > my-app.tar.gz
# 导入镜像到本地
docker load -i my-app.tar # 普通 tar 包
docker load -i my-app.tar.gz # 压缩包
二、容器管理:创建、启动、停止、进入与日志
容器是镜像的运行实例,日常操作围绕容器生命周期展开:
1. 查看容器状态
# 列出正在运行的容器
docker ps
# 列出所有容器(含停止的)
docker ps -a
# 只显示容器ID
docker ps -aq
2. 启动/停止/重启容器
# 启动容器(容器ID/名称)
docker start my-container
# 停止容器(优雅关闭,推荐)
docker stop my-container
# 强制停止容器(紧急场景,可能丢失数据)
docker kill my-container
# 重启容器
docker restart my-container
3. 进入运行中的容器
# 交互模式进入容器(分配终端+保持输入)
docker exec -it my-container /bin/bash
# 进入容器后执行单条命令(无需进入终端)
docker exec my-container ls /app
4. 查看容器日志
# 查看容器日志
docker logs my-container
# 实时跟踪日志(类似 tail -f)
docker logs -f my-container
# 查看最近100行日志
docker logs --tail 100 my-container
# 查看日志时间戳
docker logs -t my-container
5. 删除容器
# 删除停止的容器
docker rm my-container
# 强制删除运行中的容器(谨慎使用)
docker rm -f my-container
# 批量删除所有停止的容器
docker rm $(docker ps -aq)
三、数据持久化:解决容器数据丢失问题
容器默认是“临时”的,销毁后数据会丢失,因此必须通过数据卷/挂载实现持久化:
1. 挂载主机目录(bind 挂载,最常用)
# 格式:-v 主机绝对路径:容器路径[:权限]
# 示例:将主机 ./data 挂载到容器 /app/data,只读(ro)
docker run -d \
--name my-app \
-v ./data:/app/data:ro \
my-app:latest
2. 使用 Docker 管理卷(Volume,推荐)
# 创建数据卷
docker volume create pg-data
# 运行容器并挂载数据卷
docker run -d \
--name postgres \
-v pg-data:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=secret \
postgres:16
# 查看数据卷详情(含主机实际存储路径)
docker volume inspect pg-data
# 批量删除无用数据卷
docker volume prune -f
3. 内存临时挂载(临时数据,不持久)
# 挂载 tmpfs 到容器 /tmp,重启后数据消失
docker run -d --tmpfs /tmp my-app:latest
四、系统清理:释放磁盘空间
Docker 长期使用会产生大量无用镜像、容器、网络,需定期清理:
1. 一键清理(推荐,安全无风险)
# 清理停止的容器、悬空镜像、未使用网络
docker system prune
# 强制清理所有无用镜像+容器+网络(更彻底)
docker system prune -a -f
2. 分维度清理
# 清理无用容器
docker container prune -f
# 清理无用镜像(悬空镜像+未使用镜像)
docker image prune -a -f
# 清理未使用网络
docker network prune -f
# 清理未使用数据卷(谨慎,会删除未挂载的卷)
docker volume prune -f
五、其他高频操作
1. 查看容器/镜像详细信息
# 查看容器详细信息(如IP、挂载卷、环境变量)
docker inspect my-container
# 查看镜像详细信息
docker inspect my-app:latest
2. 复制文件到/从容器
# 从主机复制文件到容器
docker cp /host/path/file my-container:/container/path
# 从容器复制文件到主机
docker cp my-container:/container/path/file /host/path
3. 查看容器资源占用
# 查看所有容器资源占用(CPU、内存、磁盘IO)
docker stats
# 查看指定容器资源占用
docker stats my-container
实战总结:Docker 完整工作流
一个标准的 Docker 容器化项目工作流如下:
- 编写 Dockerfile:定义镜像构建步骤(基础镜像、依赖、代码、启动命令)。
- 构建镜像:执行
docker build -t 项目名:版本 .生成本地镜像。 - 本地测试:用
docker run单容器测试,或docker compose多容器联调。 - 镜像推送:打标签后推送到私有/公共仓库,实现跨环境共享。
- 部署运行:在服务器拉取镜像,用
docker compose启动服务(生产环境优先)。 - 日常维护:定期清理无用资源、查看容器日志、备份数据卷。
更多推荐
所有评论(0)