【Docker实战入门】从核心概念到镜像构建
Docker实战入门:从核心概念到镜像构建
Docker 作为容器化技术的代表,彻底改变了应用的部署和运行方式。它通过"一次构建,到处运行"的理念,解决了开发环境与生产环境不一致的痛点。从实战角度出发,详解 Docker 的核心概念与常用操作,快速上手 Docker 技术。
一、Docker 三大核心概念
Docker 之所以强大,源于其清晰的核心架构。理解镜像、容器和仓库的关系非常重要。
1.1 镜像(Image):应用的"模板"
镜像是什么?
镜像可以理解为一个只读的"应用模板",包含了运行应用所需的所有内容:代码、运行时环境、库文件、环境变量和配置文件。它就像一个打包好的软件安装包,但比安装包更轻量、更标准。
镜像的特点:
- 只读性:一旦构建完成,镜像内容不可修改
- 分层存储:由多个只读层叠加而成,相同层可共享,节省存储空间
- 可版本化:通过标签(Tag)区分不同版本(如
nginx:1.23
、nginx:latest
)
常用镜像操作(实战命令):
# 查看本地所有镜像(包含标签、大小、创建时间)
docker images
# 等价命令:docker image ls# 拉取镜像(从仓库下载到本地)
docker pull nginx:alpine # 拉取 nginx 的轻量 alpine 版本
docker pull mysql:8.0 # 拉取 mysql 8.0 版本# 导出镜像(备份或迁移)
docker save -o nginx-alpine.tar nginx:alpine # 导出为 tar 包# 导入镜像(从备份恢复)
docker load -i nginx-alpine.tar# 删除本地镜像(注意:需先删除依赖该镜像的容器)
docker rmi nginx:alpine
# 强制删除(即使有容器依赖,谨慎使用)
docker rmi -f nginx:alpine
小贴士:选择镜像时,优先考虑官方镜像(如
nginx
、mysql
),安全性和维护性更有保障。小版本号越新越好(如1.23
比1.21
包含更多修复)。
1.2 容器(Container):运行中的"应用实例"
容器是什么?
容器是镜像的运行实例,是一个独立的应用运行单元。如果说镜像是"模板",那么容器就是用模板创建的"应用进程"。它包含了镜像的所有内容,并在镜像只读层之上添加了一个可写层,用于运行时的数据修改。
容器的特点:
- 独立性:拥有自己的进程空间、网络空间和文件系统,与宿主机和其他容器隔离
- 轻量性:基于宿主机内核运行,无需虚拟硬件,启动时间通常在秒级
- 可移植性:同一镜像在任何支持 Docker 的环境中,运行结果一致
常用容器操作(实战命令):
# 查看运行中的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a# 启动容器(后台运行,-d 表示 detached 模式)
docker run --name my-nginx -d nginx:alpine
# 启动交互式容器(-it 表示交互式终端,常用于调试)
docker run --name my-shell -it centos:7 /bin/bash # 进入 centos 容器的命令行# 端口映射(将容器端口暴露到宿主机,格式:宿主机端口:容器端口)
docker run -d --name web-server -p 8080:80 nginx:alpine
# 此时访问宿主机的 8080 端口,等价于访问容器的 80 端口# 资源限制(限制容器使用的 CPU 和内存,避免资源耗尽)
docker run -d --name limited-app \--cpus 0.5 # 最多使用 0.5 个 CPU 核心--memory 512m # 最多使用 512MB 内存nginx:alpine# 进入运行中的容器(在容器内部执行命令)
docker exec -it my-nginx /bin/sh # 进入 nginx 容器的 shell# 停止容器
docker stop my-nginx
# 启动已停止的容器
docker start my-nginx
# 重启容器
docker restart my-nginx# 删除容器(需先停止容器,或用 -f 强制删除)
docker rm my-nginx
docker rm -f my-nginx # 强制删除运行中的容器
实战技巧:
docker run
是最常用的命令之一,记住几个核心参数:--name
指定名称、-d
后台运行、-p
端口映射、-v
数据挂载、-e
设置环境变量。
1.3 仓库(Registry):镜像的"存储库"
仓库是什么?
仓库是集中存储和分发镜像的地方,类似代码仓库(如 GitHub)。它分为公开仓库(所有人可访问)和私有仓库(仅限特定用户访问)。
常见仓库:
- Docker Hub:官方公开仓库,包含大量官方镜像(https://hub.docker.com)
- 私有仓库:企业内部搭建的仓库,用于存储敏感业务镜像(如 Harbor、Docker Registry)
仓库操作实战:
# 1. 部署本地私有仓库(基于官方 registry 镜像)
docker run -d \-p 5000:5000 \ # 映射端口--restart always \ # 开机自启-v /opt/registry-data:/var/lib/registry \ # 数据持久化--name my-registry \registry:2 # 仓库镜像# 2. 标记镜像(准备推送到私有仓库,格式:仓库地址/镜像名:标签)
docker tag nginx:alpine 192.168.1.100:5000/nginx:alpine# 3. 推送镜像到私有仓库
docker push 192.168.1.100:5000/nginx:alpine# 4. 从私有仓库拉取镜像(其他机器上)
docker pull 192.168.1.100:5000/nginx:alpine
注意:默认情况下,Docker 只允许向 HTTPS 仓库推送镜像。如果使用 HTTP 私有仓库(如本地测试),需在
/etc/docker/daemon.json
中配置信任:{ "insecure-registries": ["192.168.1.100:5000"] }
配置后重启 Docker:
systemctl restart docker
。
二、数据持久化:容器数据不丢失
容器默认是"临时的"——容器删除后,内部数据会随之丢失。但实际应用中(如数据库),数据需要长期保存。Docker 提供两种主要方式实现数据持久化:
2.1 绑定挂载(Bind Mounts):直接挂载宿主机目录
将宿主机的目录或文件直接挂载到容器中,容器内的修改会实时同步到宿主机,反之亦然。
实战示例:
# 挂载宿主机的 /opt/mysql-data 到容器的 /var/lib/mysql(mysql 数据目录)
docker run -d \--name my-mysql \-v /opt/mysql-data:/var/lib/mysql \ # 绑定挂载-e MYSQL_ROOT_PASSWORD=123456 \ # 设置环境变量(数据库密码)mysql:5.7
适用场景:
- 开发环境:需要实时同步代码(如将本地代码目录挂载到容器,修改代码无需重建镜像)
- 数据备份:直接通过宿主机目录备份数据
2.2 卷(Volumes):Docker 管理的存储
卷是由 Docker 统一管理的宿主机文件系统目录(默认路径:/var/lib/docker/volumes/
),比绑定挂载更安全、更易管理。
实战示例:
# 1. 创建卷(可选,Docker 会自动创建未指定的卷)
docker volume create nginx-data# 2. 使用卷(将 nginx-data 卷挂载到容器的 /usr/share/nginx/html)
docker run -d \--name volume-nginx \-v nginx-data:/usr/share/nginx/html \ # 卷挂载-p 80:80 \nginx:alpine# 3. 查看卷详情(包括挂载路径)
docker volume inspect nginx-data
适用场景:
- 生产环境:数据由 Docker 管理,避免误删宿主机文件
- 多容器共享数据:多个容器可挂载同一个卷,实现数据共享
最佳实践:优先使用卷(Volumes)管理数据,尤其是生产环境。绑定挂载更适合开发阶段的临时需求。
三、Dockerfile:自定义镜像的"配方"
如果官方镜像不能满足需求,可以通过 Dockerfile 自定义镜像。Dockerfile 是一个包含构建指令的文本文件,通过 docker build
命令可自动构建镜像。
3.1 常用 Dockerfile 指令(附实战说明)
指令 | 作用说明 | 实战示例 |
---|---|---|
FROM | 指定基础镜像(必须是第一条指令) | FROM centos:7 # 基于 centos 7 构建 |
WORKDIR | 设置后续命令的工作目录(类似 cd ) | WORKDIR /app # 后续命令在 /app 目录执行 |
COPY/ADD | 复制文件到镜像(ADD 支持解压和 URL 下载) | COPY . /app # 复制当前目录文件到镜像 /app |
RUN | 执行构建时命令(如安装软件) | RUN yum install -y python3 # 安装 Python3 |
ENV | 设置环境变量(构建和运行时均有效) | ENV LANG=en_US.UTF-8 # 设置编码 |
EXPOSE | 声明容器运行时监听的端口(仅声明作用) | EXPOSE 8080 # 声明监听 8080 端口 |
CMD | 容器启动命令(可被 docker run 覆盖) | CMD ["python", "app.py"] # 启动 Python 应用 |
ENTRYPOINT | 容器入口点(不可被覆盖,常与 CMD 配合) | ENTRYPOINT ["echo"] # 固定入口为 echo 命令 |
关键区别:
RUN
是"构建时执行"(镜像打包阶段),CMD/ENTRYPOINT
是"运行时执行"(容器启动阶段)。
3.2 实战:构建一个自定义 Nginx 镜像
步骤 1:创建 Dockerfile
在项目目录下新建 Dockerfile
文件:
# 基础镜像
FROM nginx:alpine# 设置工作目录
WORKDIR /usr/share/nginx/html# 复制本地文件到镜像(替换默认首页)
COPY index.html .# 安装 curl 工具(构建时执行)
RUN apk add --no-cache curl# 声明端口
EXPOSE 80# 启动命令(默认启动 nginx,可省略,因为基础镜像已包含)
CMD ["nginx", "-g", "daemon off;"]
步骤 2:准备 index.html
<!DOCTYPE html>
<html>
<head><title>My Custom Nginx</title></head>
<body><h1>Hello from Dockerfile!</h1></body>
</html>
步骤 3:构建镜像
# 格式:docker build -t 镜像名:标签 构建上下文路径
docker build -t my-nginx:v1 .
# 注意:最后的 "." 表示当前目录为构建上下文
步骤 4:运行自定义镜像
docker run -d -p 80:80 --name my-custom-nginx my-nginx:v1
访问宿主机 80 端口,即可看到自定义的首页内容,证明镜像构建成功。
总结
Docker 的核心逻辑可以概括为:用镜像打包应用,用容器运行应用,用仓库管理镜像,用挂载持久化数据。