Docker 架构详解
Docker的核心组件包括:
- Docker 客户端 - Client
- Docker 服务器 - Docker Daemon
- Docker 镜像
- Registry
- Docker 容器 - Container
Docker采用的是Clinet/Server架构。
Docker客户端
最长用的docker客户端命名是docker
,docker
支持很多操作,后面会逐步用到。另外用户也可以通过REST API与服务器通信。
#docker --help
Usage: docker COMMAND
A self-sufficient runtime for containers
Options:
--config string Location of client config files (default "/home/fbo/.docker")
-D, --debug Enable debug mode
--help Print usage
-H, --host list Daemon socket(s) to connect to
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by this CA (default "/home/fbo/.docker/ca.pem")
--tlscert string Path to TLS certificate file (default "/home/fbo/.docker/cert.pem")
--tlskey string Path to TLS key file (default "/home/fbo/.docker/key.pem")
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit
Management Commands:
config Manage Docker configs
container Manage containers
image Manage images
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
volume Manage volumes
Commands:
attach Attach local standard input, output, and error streams to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Export a container's filesystem as a tar archive
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes
Run 'docker COMMAND --help' for more information on a command.
Docker 服务器
Docker daemon 是服务器组件,以linux后台服务的方式运行。Docker daemon运行在Docker host上,负责创建、运行、监控容器,构建、存储镜像。
默认情况下Docker daemon只能响应来自本地Host的客户端请求。如果要允许远程客户请求,需要在文件中打开TCP监听:
# 编辑配置文件/etc/systemd/system/multi-user.target.wants/docker.service
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0
# 重启Docker Daemon
systemctl daemon-reload
systemctl restart docker.service
# 客户端可以远程访问服务端
docker -H <daemon_ip> info
Docker镜像
可以将Docker镜像看成一个只读模板,可以通过镜像创建容器。
镜像生成的方式有:
- 从无到有生成镜像
- 下载并使用别人创建好的现成镜像
- 在现有的镜像基础上创建新的镜像
可以将镜像的内容和创建步骤写在一个dockerfile里面,通过执行docker build <dockerfile>
来构建Docker镜像。
Docker容器
容器就是docker镜像运行的实例。
对于应用软件,docker镜像是软件生命周期的构建和打包阶段,容器是启动和运行阶段
Registry
Registry是存放docker镜像的仓库,Registry分私有和共有两种:
- Docker Hub是默认的Registry,由docker公司维护
- 出于安全考虑用户可以自己创建私有的Registry。
docker pull
从Registry上下载镜像
docker run
先下载镜像,然后再启动镜像
Docker如何工作
我们来运行第一个容器:
# 1. docker客户端执行docker run命令
root@fbo-virtual-machine:~# docker run -d -p 80:80 httpd
# 2. 本地没有发现httpd镜像
Unable to find image 'httpd:latest' locally
# 3. 从docker hub下载镜像
latest: Pulling from library/httpd
aa18ad1a0d33: Pull complete
57095d1c44f2: Pull complete
4a5cfb716767: Pull complete
5b77fd81a6f6: Pull complete
d4a7b67625a9: Pull complete
444a3c783c9e: Pull complete
2c99018b2cd1: Pull complete
# 4. 下载完成,保存到本地
Digest: sha256:7cebd11a0d5309c53202ed9e36e4704a6a38d8fe732742305a4aebfa975a21e5
Status: Downloaded newer image for httpd:latest
# 5. docker daemon启动容器
ead4a8f07e41a67e04298178b13f5973f71433f9709c9074ea90c9172d408715
# docker images查看本地镜像
root@fbo-virtual-machine:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest 6b4e03d65aa3 2 days ago 177MB
ubuntu latest ccc7a11d65b1 5 weeks ago 120MB
centos latest 328edcd84f1b 6 weeks ago 193MB
# docker ps 或者 docker container ls显示运行的容器
root@fbo-virtual-machine:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ead4a8f07e41 httpd "httpd-foreground" 5 minutes ago Up 5 minutes 0.0.0.0:80->80/tcp admiring_swanson
root@fbo-virtual-machine:~# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ead4a8f07e41 httpd "httpd-foreground" 5 minutes ago Up 5 minutes 0.0.0.0:80->80/tcp admiring_swanson
base 镜像
从上节我们可以开到,centos镜像只有200MB不到,但是我们平时使用的centos系统要远远大于这个数字,下面我们来升入讨论下。
base 镜像概念
- 不依赖其他镜像,从scratch构建。
- 其他镜像可以之为基础扩展。
linux操作系统组成
linux操作系统由内核空间和用户空间组成:
rootfs
内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。
用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。
对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。
而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。相比其他 Linux 发行版,CentOS 的 rootfs 已经算臃肿的了,alpine 还不到 10MB。
我们平时安装的 CentOS 除了 rootfs 还会选装很多软件、服务、图形桌面等,需要好几个 GB 就不足为奇了。
- 以下是CentOS的Dockerfile
不同 Linux 发行版的区别主要就是 rootfs。
比如 Ubuntu 14.04 使用 upstart 管理服务,apt 管理软件包;而 CentOS 7 使用 systemd 和 yum。这些都是用户空间上的区别,Linux kernel 差别不大。
所以 Docker 可以同时支持多种 Linux 镜像,模拟出多种操作系统环境。
基于这种特性,无论docker镜像的发行版本是什么,其内核版本只能是docker host的内核版本,比如docker host的OS是Ubuntu 16.04, 那么其上运行的CentOS 7的docker容器的kernel版本将是Ubuntu 16.04的'4.4.0-31'
镜像的分层结构
Docker支持扩展现有镜像,创建新的镜像。
FROM debain
RUN apt-get install emacs
RUN apt-get install apache2
CMD ["/bin/bash"]
构建过程如下图所示:
Dokcer镜像采用这种分层结构,最大的好处就是共享资源。修改会限定在单个容器内,这个就是容器的Copy-on-Write的特性。
可写的容器层
当容器启动时,一个新的可写容器层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫做“镜像层”。
只有容器层是可写的,容器层下面的所有镜像都是只读的。
- 添加文件 - 在容器中创建文件时,新文件被添加到容器层中。
- 读取文件 - 在容器中读取某个文件时,Docker会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存。
- 修改文件 - 在容器中修改已存在的文件时,Dokcer会从上往下依次在各个镜像层中查找此文件。找到后,立即将其复制到容器层,然后修改之。
- 删除文件 - 在容器中删除文件时,Docker也是自伤往下依次在镜像层里查找此文件。找到后,会在容器层记录下此删除操作。