Docker整理
参考资料
- https://wangchujiang.com/docker-tutorial/index.html
- https://github.com/stacklens/django-docker-tutorial/blob/master/md/01.Docker%E7%AE%80%E4%BB%8B.md
- https://docker-practice.github.io/zh-cn/install/ubuntu.html
基本概念
Docker 是一种容器化技术,可以 将应用程序及其依赖项打包成一个独立的容器,是一个开源的软件部署解决方案
Docker 本身是跨平台的,可以在 Linux、Windows 和 macOS 等操作系统上运行
Docker 利用 Linux 内核的命名空间(Namespaces)和控制组(Cgroups) 实现进程隔离和资源限制,与传统虚拟机相比更轻量
仓库、镜像、容器
仓库中集中存放各种镜像文件
有镜像才能创建对应的容器
在容器中部署项目、运行代码,Docker 使用沙箱机制隔离容器,相互之间不会有接口
为什么使用 Docker
手动部署项目的时候,我们通常会先把代码上传到服务器、然后安装相关依赖、配置环境、最后启动项目
通常这些过程都需要我们手动敲入命令,每次部署到新的机器上的时候都需要重新敲或者复制粘贴一遍
而 Docker 简化了运维工程师的工作,进行集群部署的时候就不需要一台一台地安装所需的环境
Docker 部署只需要创建一个镜像,安装好环境,再复制到集群的各个机器上,快捷并且保证了部署的一致性
虽然上述过程与自己写个部署脚本没有什么区别
但是 Docker 还能够保证每次运行的 环境都是一致的,并且 与宿主机的环境进行隔离
安装
Windows 下载安装 https://docs.docker.com/desktop/install/windows-install/
先安装好一些必要的系统工具
添加 Docker 官方软件源信息/阿里云源
安装 docker-ce,可以选择自己需要的版本
启动 Docker 后台服务
运行 hello-world 镜像,验证是否安装成功
Dockerfile 怎么写?
Docker 会根据 Dockerfile 来构建环境并生成一个 镜像
最后通过运行镜像来创建容器,完成项目部署
-
FROM
用来指定基础镜像
1 2# 指定 python 镜像,版本标签为 3.6 FROM python:3.6 -
MAINTAINER
1 2 3# 指定了 Dockerfile 的作者,或者说维护者 # 可填可不填 MAINTAINER yourname -
ENV
1 2# 用来设置环境变量 ENV PRODUCTION_ENV 1 -
ADD
用来向镜像中添加我们需要的文件,比如配置文件、代码、资源文件等等
1 2 3 4ADD ./database.ini /root # 路径是相对于 Dockerfile 所在目录的路径 ADD ./src /root ADD http://www.baidu.com /root # 路径也可以使用 URL ADD code.tar /root # tar 压缩包会被自动解压成目录 -
COPY
功能和
ADD相似
不过COPY不能用 URL,只能复制本地的文件到镜像中,并且不会自动解压 tar 压缩包 -
EXPOSE
声明容器中要使用的端口,仅仅做声明,没有实际作用
1 2EXPOSE 80 EXPOSE 80 8080 -
ENTRYPOINT
容器启动 时执行的命令,并且不会被
docker run的参数覆盖
如果指定了多个ENTRYPOINT只有 最后一个 会被执行1 2ENTRYPOINT ["可执行文件", "参数1", "参数2"] ENTRYPOINT 命令 参数1 参数2 -
WORKDIR
指定工作目录,后续的所有命令都会在这个目录下面执行
-
RUN
执行命令
1 2WORKDIR /root/project RUN pip install -r requirements.txt # python 安装依赖 -
VOLUME
声明容器中的挂载点
注意需要提供完整的目录路径
Docker 文件挂载的作用
文件挂载是将宿主机上的文件或目录与容器中的文件或目录进行关联的方式
1、数据持久化
容器内的数据通常是临时性的,当容器被删除或重新创建时,数据也会被清除
通过文件挂载,可以将容器中的数据存储到宿主机上
2、共享文件
文件挂载后,容器可以直接访问宿主机上的文件或者目录
实现容器与宿主机之间的数据交换和共享
3、配置管理
宿主机可以将配置文件传递到容器中,宿主机上修改配置文件,容器会自动加载最新的配置
方便管理容器的配置
常用命令
|
|
服务管理
|
|
镜像管理
镜像可以看作是 WorkStation 装虚拟机时候需要用到的镜像 ISO 文件
里面是一个运行环境
|
|
假设我们有一个 node.js 的项目,现在想要创建一个它的镜像
|
|
.dockerignore 文件内容如下:
|
|
Dockerfile 文件内容如下:
|
|
执行命令:
|
|
容器管理
容器可以看作是一个 系统实例
需要通过镜像来创建容器
|
|
|
|
卸载 Docker
|
|
实战
在 Docker 中部署 MySQL
适用于 Linux 系统
-
下载镜像
1 2# 拉取官方镜像,标签为 5.7 docker pull mysql:5.7.23 -
运行容器示例
1 2 3 4 5 6 7docker run --name mysql \ -p 3306:3306 \ -v $HOME/_docker/mysql/conf.d:/etc/mysql/conf.d \ # 挂载配置文件 -v $HOME/_docker/mysql/data:/var/lib/mysql \ # 挂载数据目录 -v /etc/localtime:/etc/localtime:ro \ # 同步时区 -e MYSQL_ROOT_PASSWORD=123456 \ # 设置root密码 -d mysql:5.7.23 # 后台运行参数对应的用途:
--name设置容器名字为 mysql
-p将容器的 3306 端口映射到主机的 3306 端口
-v将主机当前目录下的配置目录~/_docker/mysql/conf.d挂载到容器的/etc/mysql/conf.d
-v将主机当前目录下的数据文件 data 目录挂载到容器的/var/lib/mysql
-v将主机的 localtime 目录挂载到容器的/etc/localtime:ro
-e指定环境变量,初始化 root 用户的密码
使用镜像文件 mysql:5.7.23 -
简单操作
1 2 3 4 5 6 7 8 9# 进入 mysql 容器中 docker exec -it mysql /bin/bash # 登录 mysql mysql -uroot -p show databases; # 查看容器日志 docker logs mysql -
重启容器
1 2 3 4 5# 修改一下 MySQL 的配置文件,然后重启容器 docker restart mysql # 将容器保存为新的镜像文件 docker commit -m="modify configfile" [mysql 容器id] new_mysql:v1.1
个人项目的打包构建
先创建一个项目,目录结构如下
|
|
-
编写 Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20# 指定带有 python 3.6 环境的镜像 FROM python:3.6 # 作者 MAINTAINER geebos # 将当前目录所有文件添加到要构建的镜像中 COPY . /root/httpServer # 声明容器中的 /root/httpServer/log 目录为挂载点 VOLUME /root/httpServer/log # 设置工作目录 WORKDIR /root/httpServer # 绑定端口 EXPOSE 8000 # 设置启动命令 ENTRYPOINT python http.py -
构建镜像
首先运行
docker build -t http-server:1.0 .构建镜像
其中-t http-server:1.0指定了镜像的名字和版本号 -
通过镜像运行容器
1 2 3 4 5docker run -id \ --name http-server-container \ -p 8000:8000 \ -v d:/dockerTest/httpServer/log:/root/httpServer/log \ http-server:1.0其中:
--name http-server-container指定容器的名称为http-server-container-p 8000:8000指定端口映射
-v d:/dockerTest/httpServer/log:/root/httpServer/log绑定挂载目录
启动之后我们可以访问 http://127.0.0.1:8000
访问之后查看 d:/dockerTest/httpServer/log/log.txt 中会发现我们的请求记录被保存到宿主机上了
可以使用 docker exec -it http-server-container /bin/bash 进入到容器内部
容器管理工具 Kubernetes(K8s)
https://www.ruanyifeng.com/blog/2024/09/tke-appfabric.html
早期的企业级大型应用,通常都是一个巨大的单体软件(monolithic),包含不同功能的多个组件
哪怕只修改一个组件,也需要把整个软件重新部署一次
软件包含多个微服务,每个微服务对应一个 Docker 容器
有了 Docker,开发者开始将传统的大型单体应用拆分成多个小型的、独立的功能组件
每个组件就是一个“微服务”,并被打包成一个 Docker 容器
单体软件就变成了多个 Docker 容器组成的软件系统,这就是现在流行的"微服务架构"(microservices)
而管理这些容器的部署、扩缩容、通信和故障恢复变得极其复杂
Kubernetes 正是在“微服务时代”为解决 海量容器管理难题 而生的
Kubernetes 是谷歌开发的一款开源软件,它不是直接运行容器的,而是管理和编排成千上万容器的“操作系统”
| Kubernetes 的功能 | 解决的问题 |
|---|---|
| 统一的硬件接口 | 开发者无需关心底层服务器的差异(CPU、内存、操作系统等),K8s 将其抽象为统一的资源池 |
| 自动扩展 | 可根据应用的实际负载(如 CPU 使用率、请求数量),自动增加或减少容器的副本数 |
| 高可用与自愈 | 当某个容器崩溃时,K8s 会自动重启它;当整个节点故障时,会在其他健康节点上重新创建容器。支持滚动更新和自动回滚,保证服务不中断 |
| 服务发现与负载均衡 | 自动为容器组分配 IP 地址和 DNS 名称,并提供负载均衡,确保流量能正确分发到可用的容器上 |
| 丰富的生态系统 | 拥有大量的插件、扩展和一个非常活跃的社区,支持监控、日志、网络安全等各种功能 |
-
什么是集群 (Cluster)?
一个 Kubernetes 实例就是一个 集群。它本质上是一个由多台服务器(物理机或虚拟机)构成的集合,这些服务器被 K8s 统一管理,对外呈现为一台强大的“超级计算机”
普通应用部署在一个集群内就足够了,但企业级关键应用为了追求更高的可靠性、隔离性和灵活性,会部署在 多个集群 中,这就进入了 多集群 (Multi-Cluster) 的范畴 -
为什么要用多集群?
容灾:一个集群宕机,另一个可以立刻接管
隔离:实现不同用户/业务间的强物理隔离
避免厂商锁定:在不同云厂商部署(即多云 Multi-Cloud),获得议价能力和灵活性
好玩的测试项目
一、环境准备与基础命令
| 命令 | 用途 |
|---|---|
docker --version |
查看 Docker 客户端版本 |
docker info |
显示 Docker 系统级信息(容器/镜像数量、存储驱动等) |
二、运行第一个容器:Hello World
| 命令 | 用途 |
|---|---|
docker pull hello-world |
从 Docker Hub 拉取 hello-world 镜像 |
docker run hello-world |
基于 hello-world 镜像创建并运行容器。该镜像会打印一段测试文字后自动退出 |
docker images |
列出本地已下载的镜像 |
docker ps -a |
列出所有容器(包括已停止的)。-a 表示 all |
docker ps -aq |
只列出所有容器的 ID(-q 表示 quiet) |
docker rm $(docker ps -aq) |
删除所有容器。$(...) 会执行内部命令,将所有容器 ID 传递给 docker rm |
docker rmi hello-world |
删除 hello-world 镜像(rmi = remove image) |
练习意义:熟悉 Docker 的拉取、运行、查看、删除基本流程。
三、构建自定义 Python Web 应用镜像
3.1 创建应用文件
|
|
用途:创建一个简单的 Python HTTP 服务器脚本,监听 8000 端口。
3.2 编写 Dockerfile
|
|
用途:定义镜像构建步骤:
- 基于轻量级 Python 3.9 镜像
- 设置工作目录
/app - 将 app.py 复制到镜像中
- 声明容器运行时将使用 8000 端口
- 启动命令:
python app.py
3.3 构建镜像
| 命令 | 用途 |
|---|---|
docker build -t my-webapp:1.0 . |
根据当前目录下的 Dockerfile 构建镜像,标签为 my-webapp:1.0。注意命令末尾的 . 表示构建上下文路径 |
docker images |
确认镜像已成功构建 |
常见错误:命令 265~267 缺少构建路径或
-t参数,最终正确写法为docker build -t my-webapp:1.0 .
3.4 运行与测试自定义容器
| 命令 | 用途 |
|---|---|
docker run -d --name test-docker -p 8000:8000 my-webapp:1.0 |
后台运行容器(-d),命名为 test-docker,将宿主机 8000 端口映射到容器 8000 端口 |
curl http://localhost:8000 |
访问容器内运行的 HTTP 服务,应看到目录列表(因为是 SimpleHTTPRequestHandler) |
docker exec -it test-docker ls -la |
在运行中的容器内执行 ls -la 命令(-it 交互式终端) |
docker logs test-docker |
查看容器的标准输出日志(如 print 输出的启动信息) |
docker stop test-docker |
停止容器 |
docker rm test-docker |
删除已停止的容器 |
四、运行 MySQL 容器
|
|
用途:启动一个 MySQL 5.7 容器:
-e设置环境变量:root 密码、自动创建数据库testdb-v挂载宿主机目录~/mysql-data到容器数据目录,实现数据持久化-p 3306:3306映射端口--name mysql-test容器名称
注意:如果宿主机 3306 端口已被占用,需要更换映射端口。
五、使用 Docker Compose 部署 WordPress
5.1 创建目录与 Compose 文件
|
|
编写 docker-compose.yml:
|
|
用途:定义两个服务:
db:MySQL 数据库,数据保存在命名卷db_datawordpress:WordPress 应用,映射宿主机 8080 端口,通过服务名db连接数据库
5.2 Compose 常用命令
| 命令 | 用途 |
|---|---|
docker compose up -d |
在后台启动所有服务(-d 后台运行) |
docker compose ps |
查看当前 Compose 项目的容器状态 |
docker compose down |
停止并删除所有容器、网络(默认不删除卷) |
docker compose down -v |
额外删除命名卷(数据会丢失) |
注意:命令 295 使用了
docker compose up(前台运行),按Ctrl+C停止;命令 289 之后的cd操作是为了进入正确目录,Compose 依赖docker-compose.yml所在位置。
六、探索其他服务(Nextcloud、Media、Redis 集群)
6.1 创建多个项目目录
|
|
一次性创建多个子目录。
6.2 Nextcloud(私有云盘)
|
|
编写 docker-compose.yml:
|
|
6.3 Media(媒体服务)
类似地进入 media 目录并执行 docker compose up -d。
编写 docker-compose.yml:
|
|
6.4 Redis 集群尝试
|
|
编写 docker-compose.yml:
|
|
意图:使用多个 Redis 实例组成集群。但后续执行 redis-cli --cluster create ... 时使用的 IP 192.168.1.100 需要根据实际网卡地址修改(用户用 ifconfig 查看)。由于环境问题未完全成功,最终用 docker compose down 清理。
知识点:Redis 集群需要每个节点配置文件开启集群模式,通常配合
docker-compose.yml为每个端口定义独立服务。
七、清理与维护命令
| 命令 | 用途 |
|---|---|
docker rm <容器ID> |
删除指定容器(需先停止) |
docker rmi wordpress |
删除 wordpress 镜像 |
sudo rm -rf /var/lib/docker/tmp/* |
清理 Docker 临时文件(需谨慎,一般使用 docker system prune 更安全) |
docker system prune -a |
(推荐未出现在历史中)一键删除未使用的容器、网络、镜像和构建缓存 |
八、常见错误与注意事项
-
命令路径缺失
docker build -t my-webapp:1.0缺少最后的.导致失败,需指定构建上下文。 -
compose 命令版本
历史中同时出现了docker-compose(旧版独立命令)和docker compose(新版插件),功能相同。 -
未提前编写 docker-compose.yml
在nextcloud、media、redis-cluster目录中直接docker compose up -d会失败,因为没有定义服务。实际应先创建docker-compose.yml文件。 -
redis-cli 创建集群的 IP 选择
192.168.1.100需要改为实际宿主机 IP(可通过ifconfig或ip addr查看),且确保各 Redis 节点间网络互通。 -
直接删除 Docker 数据目录
命令 383~385 尝试手动删除/var/lib/docker下的文件是危险的,应使用 Docker 官方清理命令。
九、总结:核心 Docker 命令速查表
| 类别 | 命令 | 说明 |
|---|---|---|
| 镜像 | docker pull <镜像> |
拉取镜像 |
docker images |
列出镜像 | |
docker build -t <标签> . |
构建镜像 | |
docker rmi <镜像> |
删除镜像 | |
| 容器 | docker run [选项] <镜像> |
创建并运行容器 |
docker ps [-a] |
列出容器(含停止的) | |
docker stop <容器> |
停止容器 | |
docker rm <容器> |
删除容器 | |
docker exec -it <容器> <命令> |
在运行容器中执行命令 | |
docker logs <容器> |
查看日志 | |
| Compose | docker compose up -d |
启动服务 |
docker compose down |
停止并删除服务 | |
docker compose ps |
查看状态 |