Docker是一种容器技术,如今,它早已成了Linux相关的软件开发和布署事实上的标准。Docker是个开源项目,它彻底释放了估算虚拟化的威力,极大提升了应用的维护效率,减少了云估算应用开发的成本。通过使用Docker,除了可以让应用的布署、测试和分发都显得前所未有的高效和轻松,但是,当你在实验结束后,可以一键删掉所有镜像和临时文件,而不会在你的操作系统上的各类目录中留下垃圾(其实,Docker本身还是须要占用一些储存空间)。其实,假如你的硬碟空间足够大,是否占用储存空间也不算是主要矛盾arch linux,更重要的是,通过使用Docker,可以把环境隔离开来,防止与其它环境形成冲突。例如笔者在开发过程中,常常用到Kamailio以及FreeSWITCH的不同版本,它们又分别依赖于好多不同的第三方软件库,不同的库又有好多不同的版本……,使用Docker容器就可以挺好地避开它们之间的冲突。
假如你还不熟悉Docker,那起码应当据说过虚拟机。虚拟机是在真正的数学机上虚拟下来的“电脑”,有虚拟的CPU、内存、硬盘、网卡等。而Docker技术在虚拟机的基础上更进一步,通过Linux内核和内核功能(比如Cgroup和Namespace)来分隔进程,便于各进程相对独立运行,但能够共享宿主机的内核和网路资源等。
为了理解Docker,我们先来理解一下虚拟机。你们都晓得,计算机有CPU、内存、硬盘、网卡等最基本的硬件,而为了有效的使用这种硬件,须要一个操作系统来管理和维护它们,典型的操作系统有Windows、Linux、macOS等(手机虽然也是一台计算机,有Android和iOS等操作系统)。通常来说一台计算机上只能运行一个操作系统,为了能同时运行多个操作系统,人们发明了虚拟机。虚拟机就是使用软件模拟CPU、内存、硬盘和网卡等,这样就是在操作系统中套操作系统。相对于虚拟机,运行原先的操作系统的主机就称为宿主机。常见的虚拟机软件有VMWare和VirtualBox、以及Xen、KVM等。
但完全的虚拟各类硬件有些慢,有些重。在Linux内核中,有一个轻量级的东西叫controlgroups(即Cgroups),它可以做资源控制、进程控制和隔离。使用Cgroups做下来的虚拟化技术叫LXC(LinuxContainer),因为LXC只是使用了资源隔离,而不须要像虚拟机那样将虚拟机里全部的CPU指令“翻译”成宿主机的指令,因此更轻量级。
然而LXC用上去还比较麻烦,因此出现了好多年虽然没有流行上去,直至Docker出现。
Docker虽然并不是哪些虚拟化技术,它只是提供了一组工具,可以便捷的生成和管理镜像,启动虚拟化的容器等。所以,这种的虚拟化也不再叫虚拟机,而叫容器。就是说,在一个Linux操作系统上,可以跑好多不同的容器,不同的容器之间的资源(如CPU、进程、内存、网络、硬盘空间等)都是隔离的,不同容器里的内容可以使用不同的内容,不同版本的应用序、或依赖库等,彼此独立运行,很便捷,但它们实际上是共用内核,因此只适用于Linux。也就是说,宿主机和服务器必须都是Linux。
在Linux寄主上运行Docker开支很小,也理所其实。但人们还想在macOS上及Windows上运行Docker。最早都是以虚拟机的形式实现的,如基于VirtualBox的实现。但后来,macOS上有了性能更好的Hypervisor.Framework(xhyve是它的具体实现),Windows上也出现了WSL2,支持更好的虚拟化。
:值得一提的是谷歌最初把开源和Linux视为“毒瘤、癌症”docker --device,但后来她们表示拥抱开源,如今有了WSL及WSL2(WindowsSubsystemforLinux)以及WSA(WindowsSubsystemforAndroid),相当于直接把Linux内核做进了Windows里,直接在Windows中就可以运行Linux和Android程序。
还有一个比较有用的工具叫DockerCompose,它使用一组YAML格式的编排文件,可以更便捷地管理好多容器。最初该工具是单独提供的,不过在最新的Docker版本里,早已把该工具整合进了Docker。
假如你使用Ubuntu或则DebianLinux操作系统,可以使用如下命令一键安装(通过--mirror参数使用阿里云的镜像速率会快一些):
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
或使用DaoCloud提供的一键安装方法:
curl -sSL https://get.daocloud.io/docker | sh
在其它Linux系统上(如CentOS、RHEL等)以及macOS和Windows上的安装方式也有所不同,篇幅缘由我们就不一一介绍了,以下链接上列举了各操作系统上Docker的安装方式:
下边几个链接上也有英文的安装说明,供参考:
这儿我们简单介绍一下Docker相关的一些基本概念。
即DockerImage。上面是一些文件,相当于一个硬碟。镜像是分层的,以便传输和分享。假如日后镜像有更新,可以只下载更新过的层,而没动过的层不须要重新下载。
镜像有一个Tag属性,相当于给镜像打个记号。Tag是可选的,它就是一个字符串,假如没有Tag,默认为latest。Tag一般用于标志镜像的版本。
通过一个镜像可以启动一个容器,它是一个隔离的运行环境(可以觉得是个轻量级的虚拟机),可以步入一个容器的内部执行命令。
Docker容器在运行期间会保存一个临时的镜像,用于储存变动过的文件。容器重启临时镜像的内容就会保留,至到容器被彻底删掉。
网路最典型的使用方式是使用NAT模式,在Linux宿主机上也可以使用host模式,但前者实际上是破坏了网路隔离。
类似Github是众所周知的代码库房集聚地,Dockerhub就是Docker存盘的集聚地。除DockerHub外,其他云厂商也提供镜像服务,如附表2中的xswitch-free存盘就储存在腾讯云上。
以下命令常常用到。
启动一个容器。如:
docker run hello-world Hello from Docker!
在首次须要一个存盘时,Docker会自行从DockerHub(或指定的其他存盘服务器)上下载。其中HellofromDocker是镜像启动后复印的内容,复印后即退出,容器也会退出。假如想让镜像启动后不退出,则可以运行一个永远不退出的程序,如以下命令运行alpine(它是一个小的Linux发行版,特别小)镜像的Shell:
docker run -it alpine sh
其中,-it参数表示开启交互式终端。步入Shell环境后就可以在容器内部执行一些命令了。在宿主机上换一个终端容器,可以使用dockerps命令列举所有正在运行的存盘,如:
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 873ea4a68dc0 alpine "sh" About a minute ago Up
有了,ContainerID,就可以在宿主机上可以步入这个容器:
docker exec -it 873ea4a68dc0 sh
其实,ContainerID是手动生成的,在启动Docker存盘时可以指定一个好记的名子docker --device,如
docker run --name alpine-test --rm alpine sh
其中,--name指定一个名子(alpine-test),--rm表示容器停止运行后嵌入式linux 培训,手动删掉相关资源(假如在存盘运行期间创建了一个文件,则假如没有--rm的话,重启存盘后文件内容还在)。
有了名子,之后步入容器就可以把ContainerID换成名字,如:
docker exec -it alpine-test sh
在容器中可以使用exit退出Shell,倘若是最初启动的那种Shell退出,这么容器就手动退出。
其他常用的参数是使用-p做NAT端口映射和-e设置环境变量等。
在宿主机上可以查看标准输出(STDOUT)的日志:
docker logs alpine-test

-f参数可以步入Follow模式,即跟踪日志输出永不退出:
docker logs -f alpine-test
停止容器:
docker stop alpine-test
彻底删掉:
docker rm alpine-test
在Docker运行期间,会形成大量缓存,如手动下载的存盘,没有使用--rm手动删掉容器形成的缓存等,时间长了会占用大量硬碟空间。可以使用如下命令删掉(注意这个命令会删掉东西,在使用前确保晓得你自己在做哪些,倘若不确定的话最很多瞧瞧Docker指南或找个朋友帮助你一块看着):
docker system prune -a
此处以《Kamailio实战》示例代码中的DockerCompose文件为例(docker/kam.yml):
version: "3.3" # 配置文件的版本号 services: # 服务,可以有多个kb-kam: # 定义一个Kamailio服务,名字任意 container_name: kb-kam # 启动后,容器的名字,类似于`docker run --name 名字` image: kamailio/kamailio-ci:5.5.2-alpine # 使用的镜像,来自Docker Hub # restart: always # 崩溃后是否自动重启,在生产环境中经常使用 env_file: .env # 从该文件中自动导入一些环境变量 stdin_open: true # 是否启用标准输入 tty: true # 是否启用控制台,这个和stdin_open都开启可以在控制台输入 # command: ["/bin/sh"]# 容器启动后执行的命令,如果没有则执行构建时Dockerfile中指定的命令 privileged: true # 特权模式,如是否可以在容器中运行tcpdump抓包或gdb调试 entrypoint: # 启动后自动执行的命令 - /bin/sh # - /start-kam.sh volumes: # 挂载宿主机上的目录或文件,这些文件在容器停止后不会消失 - ../etc:/usr/local/etc/kamailio:cached - ../etc:/etc/kamailio:cached - ../start-kam.sh:/start-kam.sh networks: # 指定网络,这里我们指定了一个外部网络,方便跟其他容器共享 - kamailio-example ports: # 映射端口,这里引用了环境变量,在.env中设置 - "${KAM_SIP_PORT}:${KAM_SIP_PORT}" - "${KAM_SIP_PORT}:${KAM_SIP_PORT}/udp" networks: kamailio-example: external: true
其中,外部网路使用dockernetworkcreatekamailio-example命令创建,这样,可以将Kamailio容器与FreeSWITCH容器启动到同一个网路上(使用相同的网路地址段)。
可以通过以下命令启动容器:
docker-compose -f docker/db.yml up # 启动到前台,可以在当前Shell中看日志输入命令等 docker-compose -f docker/db.yml up -d # 启动,进入后台模式,不占用当前Shell
上述命令中,假如把up换成down则可以停止服务。从里面可以看出,有了这个YAML编排文件,可以比原始的docker少输入好多命令行参数。另外也可以将多个服务讲到同一个YAML文件中同时启停多个服务、管理她们的依赖关系等。
本文只是简单介绍了Docker和DockerCompose,可以带你们快速上手安装和使用Docker,更多的Docker使用方式还须要读者自行去找相关资料学习。

