Docker学习笔记

➡️了解 Docker

Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。Docker 项目后来还加入了 Linux基金会,并成立推动 开放容器联盟(OCI)。

Docker 自开源后受到广泛的关注和讨论,至今其 GitHub 项目 已经超过 5 万 2 千个星标和一万多个 fork。甚至由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 DockerDocker 最初是在 Ubuntu 12.04 上开发实现的;Red Hat 则从 RHEL 6.5 开始对 Docker 进行支持;Google 也在其 PaaS 产品中广泛应用 Docker
Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroupnamespace,以及 AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7 版本以后开始去除 LXC,转而使用自行开发的 libcontainer,从 1.11 开始,则进一步演进为使用 runCcontainerd

➡️Docker 生命周期

Docker 包括三个基本概念

  • 镜像(Image)
  • 容器(Container)
  • 仓库(Repository)

容器是由镜像实例化而来的,可以理解成容器是镜像的基础备份,当Docker实例化一个容器时,相当于把这个镜像备份一份,然后在这个备份的基础上启动,开始各种操作。
我们可以把镜像想象成类,把容器想象成类经过实例化后的对象。

➡️Docker 镜像

Docker的镜像概念类似于虚拟机里的镜像,是一个只读的模板,一个独立的文件系统,包括运行容器所需的数据,可以用来创建新的容器。
例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了Mysql或用户需要的其它应用程序。
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统被称为UnionFS。镜像可以基于Dockerfile构建,Dockerfile是一个描述文件,里面包含若干条命令,每条命令都会对基础文件系统创建新的层次结构。
Docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。

注:镜像是只读的,可以理解为静态文件。

镜像是一堆只读层(read-only layer)的统一视角,那些只读层重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker内部的实现细节,并且能够在主机(运行Docker的机器)的文件系统上访问到。统一文件系统(union file system)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。

注:Docker在linux上共享内核,无需虚拟化,完全支持native功能。
Docker在windows上,启用Hyper-V或者虚拟化技术,通过虚拟机来实现,不共享windows内核。
Docker在macOS上,同样用虚拟化技术xhyve或者virtualbox来实现,不共享macOS内核。
所以,在macOS和Windows下是无法直接访问到镜像的文件的。

➡️Docker 容器

Docker利用容器来运行应用。
容器(container)镜像(image)的几乎一样,区别就是容器的最上面一层是可读写的

注:相对于镜像来说容器是动态的,容器在启动的时候创建一层可写层作为最上层。
容器的定义并没有提及容器是否在运行。

➡️Running Container Definition

一个运行态容器(running container)被定义为一个可读写的统一文件系统加上隔离的进程空间和包含其中的进程。

一个容器中的进程对着个容器里的文件进行增加,删除,修改操作都将作用于容器中最上面的那一层可读写层。

➡️Image Layer Definition

镜像层(image layer)表示一层中的各种零零星星的数据,它并不仅仅包含文件系统的改变,还能包含了其他重要信息。

元数据(metadata)就是关于这个层的额外信息,它不仅能够让Docker获取运行和构建时的信息,还包括父层的层次信息。需要注意,只读层和读写层都包含元数据。

除此之外,每一层都包括了一个指向父层的指针。如果一个层没有这个指针,说明它处于最底层。

➡️Docker 仓库

如果你使用过git和github就很容易理解Docker的仓库概念。Docker 仓库的概念跟Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。
Docker 仓库是用来包含镜像的位置,Docker提供一个注册服务器(Register)来保存多个仓库,每个仓库又可以包含多个具备不同tag的镜像。Docker运行中使用的默认仓库是 Docker Hub 公共仓库。
仓库支持的操作类似git,当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。

➡️全局理解(Tying It All Together)

1
docker create <image-id>

docker create命令为指定的镜像(image)创建了一个可读可写层,构成了一个新的容器。注意,这个容器并没有运行。

1
docker start <container-id>

Docker start命令为容器文件系统创建了一个进程隔离空间。注意,每一个容器只能够有一个进程隔离空间。

1
docker run <image-id>

docker startdocker run命令的区别。

从图片可以看出,docker run命令先是利用镜像创建了一个容器,然后运行这个容器。这个命令非常的方便,并且隐藏了两个命令的细节,但从另一方面来看,这容易让用户产生误解。

注:docker run相当于docker createdocker start两个命令的组合。

1
docker ps

docker ps命令会列出所有运行中的容器。这隐藏了非运行态容器的存在。

1
docker ps –a

docker ps –a命令会列出所有的容器,不管是运行的,还是停止的。

1
docker images

docker images命令会列出了所有顶层(top-level)镜像。实际上,在这里我们没有办法区分一个镜像和一个只读层,所以我们提出了top-level镜像。只有创建容器时使用的镜像或者是直接pull下来的镜像能被称为顶层(top-level)镜像,并且每一个顶层镜像下面都隐藏了多个镜像层。

1
docker images –a

docker images –a命令列出了所有的镜像,也可以说是列出了所有的可读层。如果你想要查看某一个image-id下的所有层,可以使用docker history来查看。

1
docker stop <container-id>

docker stop命令会向运行中的容器发送一个SIGTERM的信号,然后停止所有的进程。

1
docker kill <container-id>

docker kill命令向所有运行在容器中的进程发送了一个不友好的SIGKILL信号。

1
docker pause <container-id>

docker stopdocker kill命令会发送UNIX的信号给运行中的进程,docker pause命令则不一样,它利用了cgroups的特性将运行中的进程空间暂停。但是这种方式的不足之处在于发送一个SIGTSTP信号对于进程来说不够简单易懂,以至于不能够让所有进程暂停。

1
docker rm <container-id>

docker rm命令会移除构成容器的可读写层。注意,这个命令只能对非运行态容器执行。

1
docker rmi <image-id>

docker rmi命令会移除构成镜像的一个只读层。你只能够使用docker rmi来移除最顶层(top level layer)(也可以说是镜像),你也可以使用-f参数来强制删除中间的只读层。

1
docker commit <container-id>

docker commit命令将容器的可读写层转换为一个只读层,这样就把一个容器转换成了不可变的镜像。

1
docker build

docker build命令会反复的执行多个命令。

build命令根据Dockerfile文件中的FROM指令获取到镜像,然后重复地

  1. run(create和start)
  2. 修改
  3. commit

在循环中的每一步都会生成一个新的层,因此许多新的层会被创建。

1
docker exec <running-container-id>

docker exec命令会在运行中的容器执行一个新进程

1
docker inspect <container-id> or <image-id>

docker inspect命令会提取出容器或者镜像最顶层的元数据。

1
docker save <image-id>

docker save命令会创建一个镜像的压缩文件,这个文件能够在另外一个主机的Docker上使用。和export命令不同,这个命令为每一个层都保存了它们的元数据。这个命令只能对镜像生效。

1
docker export <container-id>

docker export命令创建一个tar文件,并且移除了元数据和不必要的层,将多个层整合成了一个层,只保存了当前统一视角看到的内容。

注:expoxt后的容器再importDocker中,通过docker images –tree命令只能看到一个镜像;而save后的镜像则不同,它能够看到这个镜像的历史镜像。

1
docker history <image-id>

docker history命令递归地输出指定镜像的历史镜像。

➡️Docker 命令

参考链接

➡️Docker run

1
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

OPTIONS说明:

  • -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
  • -d: 后台运行容器,并返回容器ID;
  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -P: 随机端口映射,容器内部端口随机映射到主机的高端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  • –name=“nginx-lb”: 为容器指定一个名称;
  • –dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
  • –dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
  • -h “mars”: 指定容器的hostname;
  • -e username=“ritchie”: 设置环境变量;
  • –env-file=[]: 从指定文件读入环境变量;
  • –cpuset=“0-2” or --cpuset=“0,1,2”: 绑定容器到指定CPU运行;
  • -m :设置容器使用内存最大值;
  • –net=“bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
  • –link=[]: 添加链接到另一个容器;
  • –expose=[]: 开放一个端口或一组端口;
  • –volume , -v: 绑定一个卷

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为mynginx。
docker run --name mynginx -d nginx:latest

# 使用镜像nginx:latest以后台模式启动一个容器,并将容器的80端口映射到主机随机端口。
docker run -P -d nginx:latest

# 使用镜像 nginx:latest,以后台模式启动一个容器,将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data。
docker run -p 80:80 -v /data:/data -d nginx:latest

# 绑定容器的 8080 端口,并将其映射到本地主机 127.0.0.1 的 80 端口上。
$ docker run -p 127.0.0.1:80:8080/tcp ubuntu bash

# 使用镜像nginx:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
runoob@runoob:~$ docker run -it nginx:latest /bin/bash
root@b85456f75:/#

➡️Docker start/stop/restart 命令

docker start :启动一个或多个已经被停止的容器
docker stop :停止一个运行中的容器
docker restart :重启容器

1
2
3
docker start [OPTIONS] CONTAINER [CONTAINER...]
docker stop [OPTIONS] CONTAINER [CONTAINER...]
docker restart [OPTIONS] CONTAINER [CONTAINER...]

实例:

1
2
3
4
5
6
7
8
# 启动已被停止的容器myrunoob
docker start myrunoob

# 停止运行中的容器myrunoob
docker stop myrunoob

# 重启容器myrunoob
docker restart myrunoob

➡️Docker attach 命令

docker attach:连接到正在运行中的容器。

1
docker attach [OPTIONS] CONTAINER

要attach上去的容器必须正在运行,可以同时连接上同一个container来共享屏幕(与screen命令的attach类似)。
官方文档中说attach后可以通过CTRL-C来detach,但实际上经过我的测试,如果container当前在运行bash,CTRL-C自然是当前行的输入,没有退出;如果container当前正在前台运行进程,如输出nginx的access.log日志,CTRL-C不仅会导致退出容器,而且还stop了。这不是我们想要的,detach的意思按理应该是脱离容器终端,但容器依然运行。好在attach是可以带上–sig-proxy=false来确保CTRL-D或CTRL-C不会关闭容器。

➡️Docker create 命令

创建一个新的容器

1
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
➡️Options
Name,shorthandDefaultDescription
–add-hostAdd a custom host-to-IP mapping (host:ip)
–attach , -aAttach to STDIN, STDOUT or STDERR
–blkio-weightBlock IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
–blkio-weight-deviceBlock IO weight (relative device weight)
–cap-addAdd Linux capabilities
–cap-dropDrop Linux capabilities
–cgroup-parentOptional parent cgroup for the container
–cidfileWrite the container ID to the file
–cpu-countCPU count (Windows only)
–cpu-percentCPU percent (Windows only)
–cpu-periodLimit CPU CFS (Completely Fair Scheduler) period
–cpu-quotaLimit CPU CFS (Completely Fair Scheduler) quota
–cpu-rt-periodAPI 1.25+
Limit CPU real-time period in microseconds
–cpu-rt-runtimeAPI 1.25+
Limit CPU real-time runtime in microseconds
–cpu-shares , -cCPU shares (relative weight)
–cpusAPI 1.25+
Number of CPUs
–cpuset-cpusCPUs in which to allow execution (0-3, 0,1)
–cpuset-memsMEMs in which to allow execution (0-3, 0,1)
–deviceAdd a host device to the container
–device-cgroup-ruleAdd a rule to the cgroup allowed devices list
–device-read-bpsLimit read rate (bytes per second) from a device
–device-read-iopsLimit read rate (IO per second) from a device
–device-write-bpsLimit write rate (bytes per second) to a device
–device-write-iopsLimit write rate (IO per second) to a device
–disable-content-trusttrueSkip image verification
–dnsSet custom DNS servers
–dns-optSet DNS options
–dns-optionSet DNS options
–dns-searchSet custom DNS search domains
–domainnameContainer NIS domain name
–entrypointOverwrite the default ENTRYPOINT of the image
–env , -eSet environment variables
–env-fileRead in a file of environment variables
–exposeExpose a port or a range of ports
–gpusAPI 1.40+
GPU devices to add to the container (‘all’ to pass all GPUs)
–group-addAdd additional groups to join
–health-cmdCommand to run to check health
–health-intervalTime between running the check (ms丨s丨m丨h) (default 0s)
–health-retriesConsecutive failures needed to report unhealthy
–health-start-periodAPI 1.29+
Start period for the container to initialize before starting health-retries countdown (ms丨s&丨m丨h) (default 0s)
–health-timeoutMaximum time to allow one check to run (ms丨s丨m丨h) (default 0s)
–helpPrint usage
–hostname , -hContainer host name
–initAPI 1.25+
Run an init inside the container that forwards signals and reaps processes
–interactive , -iKeep STDIN open even if not attached
–io-maxbandwidthMaximum IO bandwidth limit for the system drive (Windows only)
–io-maxiopsMaximum IOps limit for the system drive (Windows only)
–ipIPv4 address (e.g., 172.30.100.104)
–ip6IPv6 address (e.g., 2001:db8::33)
–ipcIPC mode to use
–isolationContainer isolation technology
–kernel-memoryKernel memory limit
–label , -lSet meta data on a container
–label-fileRead in a line delimited file of labels
–linkAdd link to another container
–link-local-ipContainer IPv4/IPv6 link-local addresses
–log-driverLogging driver for the container
–log-optLog driver options
–mac-addressContainer MAC address (e.g., 92:d0:c6:0a:29:33)
–memory , -mMemory limit
–memory-reservationMemory soft limit
–memory-swapSwap limit equal to memory plus swap: ‘-1’ to enable unlimited swap
–memory-swappiness-1Tune container memory swappiness (0 to 100)
–mountAttach a filesystem mount to the container
–nameAssign a name to the container
–netConnect a container to a network
–net-aliasAdd network-scoped alias for the container
–networkConnect a container to a network
–network-aliasAdd network-scoped alias for the container
–no-healthcheckDisable any container-specified HEALTHCHECK
–oom-kill-disableDisable OOM Killer
–oom-score-adjTune host’s OOM preferences (-1000 to 1000)
–pidPID namespace to use
–pids-limitTune container pids limit (set -1 for unlimited)
–platformexperimental (daemon)API 1.32+
Set platform if server is multi-platform capable
–privilegedGive extended privileges to this container
–publish , -pPublish a container’s port(s) to the host
–publish-all , -PPublish all exposed ports to random ports
–read-onlyMount the container’s root filesystem as read only
–restartnoRestart policy to apply when a container exits
–rmAutomatically remove the container when it exits
–runtimeRuntime to use for this container
–security-optSecurity Options
–shm-sizeSize of /dev/shm
–stop-signalSIGTERMSignal to stop a container
–stop-timeoutAPI 1.25+
Timeout (in seconds) to stop a container
–storage-optStorage driver options for the container
–sysctlSysctl options
–tmpfsMount a tmpfs directory
–tty , -tAllocate a pseudo-TTY
–ulimitUlimit options
–user , -uUsername or UID (format: <name丨uid>[:<group丨gid>])
–usernsUser namespace to use
–utsUTS namespace to use
–volume , -vBind mount a volume
–volume-driverOptional volume driver for the container
–volumes-fromMount volumes from the specified container(s)
–workdir , -wWorking directory inside the container