参考文献

容器

  • 容器是基于镜像创建的可运行实例,并且单独存在.
  • 一个镜像可以创建多个容器.

容器实现原理

chroot

chroot是在Unix和Linux系统的一个操作,针对正在运作的软件行程和它的子进程,改变它外显的根目录.一个运行在这个环境下,经由chroot设置根目录的程序,它不能够对这个指定根目录之外的文件进行访问动作,不能读取,也不能更改它的内容.

  • chroot就是可以改变某进程的根目录,使这个程序不能访问目录之外的其他目录

Namespace

Namespace 是 Linux 内核的一项功能,该功能对内核资源进行隔离,使得容器中的进程都可以在单独的命名空间中运行,并且只可以访问当前容器命名空间的资源.Namespace 可以隔离进程 ID、主机名、用户 ID、文件名、网络访问和进程间通信等相关资源.

  • Docker 主要用到以下五种命名空间.

    • pid namespace:用于隔离进程 ID.
    • net namespace:隔离网络接口,在虚拟的 net namespace 内用户可以拥有自己独立的 IP、路由、端口等.
    • mnt namespace:文件系统挂载点隔离.
    • ipc namespace:信号量,消息队列和共享内存的隔离.
    • uts namespace:主机名和域名的隔离.

Cgroups

  • Cgroups 是一种 Linux 内核功能,可以限制和隔离进程的资源使用情况(CPU、内存、磁盘 I/O、网络等).在容器的实现中,Cgroups 通常用来限制容器的 CPU 和内存等资源的使用.

联合文件系统

  • 联合文件系统,又叫 UnionFS,是一种通过创建文件层进程操作的文件系统,因此,联合文件系统非常轻快.Docker 使用联合文件系统为容器提供构建层,使得容器可以实现写时复制以及镜像的分层构建和存储.常用的联合文件系统有 AUFS、Overlay 和 Devicemapper 等.

容器的生命周期

  • created: 初建状态
  • running: 运行状态
  • stopped: 停止状态
  • paused: 暂停状态
  • deleted: 删除状态
1
2
3
4
5
6
7
8
9
10
graph LR
Docker镜像(Docker镜像) -->|docker create| 初建状态(初建状态)
Docker镜像(Docker镜像) -->|docker run|运行状态(运行状态)
初建状态(初建状态) -->|docker start|运行状态(运行状态)
运行状态(运行状态) -->|docker restart|运行状态(运行状态)
运行状态(运行状态) -->|docker stop| 停止状态(停止状态)
停止状态(停止状态) -->|docker start|运行状态(运行状态)
运行状态(运行状态) -->|docker paused| 暂停状态(暂停状态)
暂停状态(暂停状态) -->|docker unpaused| 运行状态(运行状态)
停止状态(停止状态) -->|docker rm| 删除状态(删除状态)

容器的管理

创建并启动容器

1
2
3
docker create -it --name=[container] image_name

docker start container

运行容器

1
docker run -it --name=[container] image_name [command][args]
  • 检查本地是否存在指定的镜像,不存在就从公有仓库下载
  • 利用镜像创建并启动一个容器
  • 分配一个文件系统,并在只读的镜像层外面挂载一层可读层
  • 从宿主主机配置的网桥接口中桥接一个虚拟接口道容器中去.
  • 从地址池配置一个IP地址给容器
  • 执行用户指定的应用程序
  • 执行完毕后容器被终止
  • Options:
    • --name=容器的新名字:为容器指定一个名称
    • -d: 在后台运行容器,并返回容器ID
    • -i:以交互模式运行容器,通常与-t同时使用
    • -t:为容器重新分配一个伪输入终端
    • -P:随机端口映射
    • -p: :指定端口映射
      • ip:hostPort:containerPort 将Docker容器的端口映射到主机的特定IP地址和端口上
        • 192.168.0.1:80:8080
      • ip::containerPort 将Docker容器的端口映射到主机上任何可用的端口上
        • 192.168.0.1::8080
      • hostPort:containerPort 将Docker容器的端口映射到主机的特定端口上
        • 80:8080
      • containerPort 将Docker容器的端口映射到主机上任何可用的端口上
      • 指定监听UDP端口
        • 80:8080/udp

停止容器

1
docker stop [-t|--time[=10]]
  • 如果等待一段时间后,容器仍然没有退出,则会发送SIGKILL强制终止容器.
  • 处于终止状态的容器可以使用docker ps -a来查看

重启容器

1
2
3
4
docker restart container

# 重启处于退出状态的容器
docker restart $(docker ps -aq -f status=exited)

进入容器

1
docker exec -it container
1
2
PID=$(docker inspect --format "{{.State.Pid}}" container)
nsenter --target $PID --mount --uts --ipc --net --pid

删除容器

1
docker rm [options] container[ container...]
  • 删除正在运行中的容器,必须加-f或者--force参数,如docker rm -f container[ container...]
1
2
3
4
docker rm $(docker ps -aq)
// 删除所有已停止的容器 -v的作用意味着当所有由Docker管理的数据卷已经没有和任何容器关联时,都会一律删除.
docker rm -v $(docker ps -aq -f status=exited)
// 为了避免已停止的容器的数量不断增加,可以在执行docker run 的时候加上--rm参数,它的作用是当容器退出时,容器和相关的文件系统会被一并删掉

导出容器到文件

1
2
3
docker export container

docker export cowboy > cowboy.tar

导入容器

1
2
3
docker import [options] file|URL[repository[:tag]]

docker import cowboy.tar cowboy:new
  • 注意: 启动exportimport命令导出导入的镜像必须加/bin/bash或者其他/bin/sh,否则会报错。
    1
    docker: Error response from daemon: No command specified.

列出所有容器

1
docker ps -aq

容器和主机之间复制文件和目录

  • docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
    
    1
    2
    3
    4
    5

    - 从容器中复制文件到主机: `docker cp container_nginx:/usr/local/testA.txt /usr/local/`

    - ```
    docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
    - 从主机复制文件到容器: `docker cp /usr/local/testB.txt container_nginx:/usr/local/`

暂停和恢复容器

1
2
docker pause container
docker unpause container

清理所有Exited状态的容器

1
sudo docker ps -a | grep Exit | cut -d ' ' -f 1 | xargs sudo docker rm

查看容器内日志

1
docker logs [options] container
  • -f: 追踪
  • -t: 显示时间
  • --tail: 从尾部显示

查看容器内进程

1
docker top container

查看容器占用资源

1
docker stats

列出当前正在运行的容器的PID

1
docker ps -q | xargs -I {} sh -c 'echo "Container ID: {}"; docker inspect --format "Container Name: {{.Name}} | PID: {{.State.Pid}}" {}; echo "";'

查看容器内部细节

1
docker inspect container
  • 使用-f或者--format标志来选定查看结果

    1
    2
    3
    4
    5
    6
    7
    8
    $ docker inspect --format='{{.State.Running}}' mysql8
    true
    # 指定多个容器
    $ docker inspect --format='{{.Name}} {{.State.Running}}' mysql8 mysql8.0.22
    /mysql8 true
    /mysql8.0.22 true
    # 查看容器IP地址
    $ docker inspect redis-replication-1 -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'

查看容器内部端口docker容器的--restart=always参数

1
docker update --restart=always 容器名字
Flag Description
no 不要自动重启容器.(默认)
on-failure[:max-retries] 如果容器因错误而退出(表现为非零退出代码),请重新启动容器.(可选)使用该选项限制 Docker 守护进程尝试重新启动容器的次数:max-retries.该on-failure策略仅在容器因失败退出时提示重新启动.如果守护进程重新启动,它不会重新启动容器.
always 如果容器停止,请务必重新启动容器.如果手动停止,则只有当 Docker 守护进程重新启动或手动重新启动容器本身时,它才会重新启动.
unless-stopped 与 类似always,只不过当容器停止(手动或其他方式)时,即使 Docker 守护进程重新启动,它也不会重新启动.

限制容器资源

1
docker update --cpuset-cpus "2" --memory "8G" --memory-swap "8G" <RunningContainerNameOrID>