镜像
这命令也很简单,run 的意思就是要启动一个容器
# docker run -d centos/httpd:latest
-d 参数里 d 是 Daemon 的首字母,也就是让容器在后台运行。最后一个参数 centos/httpd:latest 指定了具体要启动哪一个镜像,比如这里咱们启动的是 centos/httpd 这个镜像的 latest 版本。
其实,镜像就是一个特殊的文件系统。它提供了容器中程序执行需要的所有文件。具体来说,就是应用程序想启动,需要三类文件:相关的程序可执行文件、库文件和配置文件,这三类文件都被容器打包做好了。
Dockerfile
Dockerfile 的每一行,第一个大写的词都是 Dockerfile 专门定义的指令,也就是 FROM、RUN、COPY、ADD、CMD,这些指令都很基础,所以我们不做详细解释了,你可以参考 Dockerfile 的官方文档。
# cat Dockerfile
FROM centos:8.1.1911
RUN yum install -y httpd
COPY file1 /var/www/html/
ADD file2.tar.gz /var/www/html/
CMD ["/sbin/httpd", "-D", "FOREGROUND"]
下面这个命令中 -f ./Dockerfile 指定 Dockerfile 文件,-t registry/httpd:v1 指定了生成出来的镜像名,它的格式是"name:tag",这个镜像名也是后面启动容器需要用到的。
# docker build -t registry/httpd:v1 -f ./Dockerfile .
docker build 执行成功之后,我们再运行 docker images 这个命令,就可以看到生成的镜像了。
# docker images
REPOSITORY TAG IMAGEID CREATED SIZE
registry/httpd v1 c682fc3d4b9a 4 seconds ago 277MB
我们运行下面这个 docker exec 命令,也就是执行 docker exec c5a9ff78d9c1 ps -ef ,可以看到 httpd 的服务进程正在容器的空间中运行。
# docker exec c5a9ff78d9c1 ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
apache 6 1 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
apache 7 1 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
apache 8 1 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
apache 9 1 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
容器是什么
两个术语 Namespace 和 Cgroups
Namespace
容器内
# docker exec c5a9ff78d9c1 ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
apache 6 1 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
apache 7 1 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
apache 8 1 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
apache 9 1 0 01:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
宿主机
# ps -ef | grep httpd
UID PID PPID C STIME TTY TIME CMD
root 20731 20684 0 18:59 ? 00:00:01 /sbin/httpd -D FOREGROUND
48 20787 20731 0 18:59 ? 00:00:00 /sbin/httpd -D FOREGROUND
48 20788 20731 0 18:59 ? 00:00:06 /sbin/httpd -D FOREGROUND
48 20789 20731 0 18:59 ? 00:00:05 /sbin/httpd -D FOREGROUND
48 20791 20731 0 18:59 ? 00:00:05 /sbin/httpd -D FOREGROUN
containerd是宿主机上的一个守护进程,用来建立容器。每建立一个容器,就会有一个shim进程,它是容器中init进程的父进程。
containerd 启动当容器的时候先会启动一个shim, 然后由shim运行runc去创建container. 这样相当于一个shim来管理一个container. shim作为container的“父进程”, 接管了容器的stdin/stdout, containerd服务出问题,不会影响到用户的container。
Namespace 尽管类型不同,其实都是为了隔离容器资源:
- PID Namespace 负责隔离不同容器的进程
- Network Namespace 又负责管理网络环境的隔离
- Mount Namespace 管理文件系统的隔离。
Cgroups
Cgroups 可以对指定的进程做各种计算机资源的限制,比如限制 CPU 的使用率,内存使用量,IO 设备的流量等等。
了解几种比较常用的 Cgroups 子系统:
- CPU 子系统,用来限制一个控制组(一组进程,你可以理解为一个容器里所有的进程)可使用的最大 CPU。
- memory 子系统,用来限制一个控制组最大的内存使用量。
- pids 子系统,用来限制一个控制组里最多可以运行多少个进程。
- cpuset 子系统, 这个子系统来限制一个控制组里的进程可以在哪几个物理 CPU 上运行。
memory 子系统的限制参数最简单,所以下面我们就用 memory 子系统为例。
对于启动的每个容器,都会在 Cgroups 子系统下建立一个目录,在 Cgroups 中这个目录也被称作控制组,比如下图里的"docker-""docker-"等。然后我们设置这个控制组的参数,通过这个方式,来限制这个容器的内存资源。
在每个 Cgroups 子系统下,对应这个容器就会有一个目录 docker-c5a9ff78d9c1……这个容器的 ID 号,容器中所有的进程都会储存在这个控制组中 cgroup.procs 这个参数里。
我们把(2* 1024 * 1024 * 1024 = 2147483648)这个值,写入 memory Cgroup 控制组中的 memory.limit_in_bytes 里,这样设置后,cgroup.procs 里面所有进程 Memory 使用量之和,最大也不会超过 2GB。
# cd /sys/fs/cgroup/memory/system.slice/docker-c5a9ff78d9c1fedd52511e18fdbd26357250719fa0d128349547a50fad7c5de9.scope
# cat cgroup.procs
20731
20787
20788
20789
20791
# echo 2147483648 > memory.limit_in_bytes
# cat memory.limit_in_bytes
2147483648
简单总结
目前呢,你只需要先记住这两个技术的作用,Namespace 帮助容器来实现各种计算资源的隔离,Cgroups 主要限制的是容器能够使用的某种资源量。
docker stop
containerd会先向容器中的init进程发送SIGTERM,如果init进程注册了SIGTERM
handler(并且handler让进程退出了)那么整个容器就退出了,如果容器的init进程没有注册SIGTERM, 那么过30秒, containerd再向容器的init进程发送SIGKILL.
容器对应的memory cgroup 目录
docker inspect 4d3cf63512a2 | grep \"Pid\"
"Pid": 4384,
# cat /proc/4384/cgroup | grep memory
5:memory:/system.slice/docker-4d3cf63512a2b89c0982724a6c12cb9b69781676aa93ab4fb2060f47908c6b94.scope
-----------------
-bash-4.2# pwd
/sys/fs/cgroup/memory
-bash-4.2# find . -name *8c28cc9c5db8*
./system.slice/docker-8c28cc9c5db88bf08b6ccc79aed58b8ec4afaeb1ef7ff27aaabfa60229824c08.scope
基础镜像怎么做?
docker base image, 拿centos为例子,可以建一个目录,让后把需要的rpm 安装在这个目录下面,然后把目录打成一个tarball, 用docker import成为一个base image.