第四章、Docker 容器的操作

前面我们讲过,在 Docker 中,容器(Container)是一个轻量级、可执行的独立软件包,它包含了运行某个应用所需的所有内容:根文件系、网络、名字空间、运行时环境、系统工具、运行时库和配置等信息。

Docker 的容器有如下特性:

  1. 基于镜像运行
    • 容器是从Docker镜像创建的实例。镜像类似于模板,而容器是模板的运行实例(类似于面相对象中的 "类" 和 "对象" 的关系)。
    • 例如:你可以从使用 mysql 镜像运行多个独立的 mysql 容器,每个mysql 后台服务用于不同的业务。
  2. 隔离性
    • 每个容器拥有独立的文件系统、网络、进程空间(通过Linux内核的cgroups和namespaces实现)。
    • 容器之间互不干扰,但可以通过配置进行通信。
  3. 轻量级
    • 容器共享宿主机的操作系统内核,无需像虚拟机(VM)那样模拟完整操作系统,因此启动更快、资源占用更少。
  4. 临时性(可销毁)
    • 容器默认是无状态的,停止后数据会丢失(除非使用卷(Volumes)持久化存储)。
  5. 可移植性
    • 容器可以在相同宿主操作系统的 Docker 环境中制作,并能在相同类型的宿主操作系统上运行(有限的可移植性)。
  6. 不可跨硬件平台运行
    • 在基于ARM的平台中创建的镜像均为基于 ARM 平台的,无法在 x86 平台上运行。
    • 跨平台的容器无法运行,会出现格式错误,如下图所示:

      跨平台的容器无法运行

Docker 容器的结构模型

一个容器通常有一个或多个只读的镜像层(如下图的 74fe38d11401 )和一个可写层(Writeable layer)组成,可写层用于容器运行时存放临时数据。

如下图所示:

上图最上层的 running job 就是 容器主程序

一个容器一定要有一个 容器主程序,并且这个 容器主程序 一旦推向后台或者退出,则整个容器运行结束(重要)。

1. 创建并运行 docker 容器

使用 docker run 命令可以创建并运行一个容器。

docker run 命令

命令格式

docker run [选项] 镜像名[:标签]或镜像ID [命令] [参数...]

命令别名: docker container run

命令格式说明

常用选项

选项
说明
-d
在后台运行容器( detached 模式),打印容器ID
--name
指定容器名称
-p <宿主机端口>:<容器端口>
端口映射(如 -p 80:8080)
-v <宿主机路径>:<容器路径>
挂载卷,将宿主机文件或文件夹挂载在容器内某个路径下)。
-e 环境变量名=值
设置容器内环境变量(如 -e MYSQL_ROOT_PASSWORD=123456)
--restart=重启模式
退出后重启策略(如 --restart=always),默认是 no 不重启,always 退出就重启,unless-stopped 不会恢复手动停止的容器,on-failure[:max-retries] 容器非正常退出时重启(可指定最大重试次数)。
--rm
当容器退出后自动删除容器。
--network
指定网络连接方式(如 --network=host 直接暴露主机端口,bridge 容器间通信(默认),container:<容器名或ID>共享其他容器的网络。none 容器不配置任何网络
-i
交互式终端,保持标准输入 STDIN 打开。
-t
分配一个伪终端(通常和 -i 选项一起使用)。
-w
指定容器内部的工作路径
-ip <IP地址>
设置容器运行时的 IP 地址,如: -ip 127.17.0.100
-cpus <数字>
设置容器运行的占用 CPU 的数量。
-m <字节数>
设置容器的内存限制
-h <主机名>
设置容器的主机名

使用 sudo docker run --help 可以查看全部选项。

示例

weimingze@mzstudio:~$ sudo docker run \
    --name mysql_server \
    -p 3306:3306 \
    -e MYSQL_ROOT_PASSWORD=weimingze.com \
    -v /home/weimingze/mysql_vol/data:/var/lib/mysql \
    -v /home/weimingze/mysql_vol/logs:/var/log/mysql \
    --restart=unless-stopped \
    -d \
    mysql
4d68e66019f347a444aed488acfc8aec7ebf3c9210f6ccb0467a03186eceb483
weimingze@mzstudio:~$

反斜杠 \ 是 Linux Shell 的折行符,当命令行太长时,可以在一行的末尾写入 反斜杠 \,然后在下一行可以继续输入此命令的选项和参数而不会执行当前命令。

下面我们来详细解读上述 docker run 的选项:

  1. --name mysql_server 是为此运行的容器取一个名字 mysql_server,便于查找、停止此容器等操作。
  2. -p 3306:3306,将容器内部的 3306 端口号映射到 宿主机的 3306 端口号。也就是 宿主机通过 3306 端口号和容器内的 3306 对应。不映射,我们不能从外部访问服务器。
  3. -e MYSQL_ROOT_PASSWORD=weimingze.com 通过环境变量 MYSQL_ROOT_PASSWORD 来设定 容器内 MySQL 服务器的 root 密码是 weimingze.com, 这个环境变量的名称是制作镜像的作者来定义的。
  4. -v /home/weimingze/mysql_vol/data:/var/lib/mysqlMySQL 容器内部的 /var/lib/mysql 映射成宿主机的 /home/weimingze/mysql_vol/data 文件夹。/var/lib/mysql 是 MySQL 数据保存数据的默认路径
  5. -v /home/weimingze/mysql_vol/logs:/var/log/mysql 将 MySQL 保存日志的路径 /var/log/mysql 映射成宿主机的路径,便于查看和保存。
  6. --restart=unless-stopped 如果容器非正常退出则重新启动容器。
  7. -d 将 正在运行的容器推向后台运行,脱离终端。去掉此选项,终端会连接 容器主进程 并能看到容器主进程的输出结果。使用 Control + c 可以终止容器运行。

  8. 终端输出 4d68e66019f347a444aed488acfc8aec7ebf3c9210f6ccb0467a03186eceb483 是容器的 ID。

宿主机 /home/weimingze/mysql_vol 的内容如下:

weimingze@mzstudio:~$ tree mysql_vol/
mysql_vol/
├── data
│   ├── #ib_16384_0.dblwr   ├── #ib_16384_1.dblwr   ├── #innodb_redo  [error opening dir]   ├── #innodb_temp  [error opening dir]   ├── auto.cnf
│   ├── binlog.000001
│   ├── binlog.000002
│   ├── binlog.000003
│   ├── binlog.index
│   ├── ca-key.pem
│   ├── ca.pem
│   ├── client-cert.pem
│   ├── client-key.pem
│   ├── ib_buffer_pool
│   ├── ibdata1
│   ├── ibtmp1
│   ├── mysql  [error opening dir]   ├── mysql.ibd
│   ├── mysql.sock -> /var/run/mysqld/mysqld.sock
│   ├── mysql_upgrade_history
│   ├── performance_schema  [error opening dir]   ├── private_key.pem
│   ├── public_key.pem
│   ├── server-cert.pem
│   ├── server-key.pem
│   ├── sys  [error opening dir]   ├── undo_001
│   └── undo_002
└── logs

8 directories, 23 files

可见容器内的 mysql 启动后将运行的数据库内容映射到了宿主机的 /home/weimingze/mysql_vol 文件夹下。这样可以保证数据的安全,一但容器损坏,数据还在,还可以恢复。