Docker容器之旅

一、前言

Docker是软件工业上的集装箱技术

回顾,在没有集装箱出现以前,传统运输行业中,会存在这些问题:

在运输过程中,货物损坏
装卸、运输货物,效率低下
运输手续繁多及运输环节多
劳动强度大,及船舶周转慢

在集装箱出现后,完全改变了这种状况,是由于集装箱:

规则标准化,大大减少了包装费用
大大提升了货物装卸效率、及运输效率
不同种运输工具之间转换更容易

所以,集装箱出现是传统行业中的一次重大变革

传统软件行业中存在的问题

软件更新发布低效
业务无法敏捷
环境一致性,难于保证
不同环境之间迁移成本太高
软件开发商,交付实施周期长—成本高

有了Docker,以上问题在很大程度上可以得到解决

二、Docker介绍

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

Docker使用Google公司推出的Go语言进行开发实现,基于Linux内核的cgroup,namespace,以及AUFS类的UnionFS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器

Docker在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得Docker技术比虚拟机技术更为轻便、快捷

与传统虚拟机相比

传统虚拟机

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程

Docker

而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便

Docker的优势

  • 更高效的利用系统资源
  • 更快速的启动时间
  • 一致的运行环境
  • 持续交付和部署
  • 更轻松的迁移
  • 更轻松的维护和扩展

对比传统虚拟机总结

特性 容器 虚拟机
启动 秒级 分钟级
硬盘使用 一般为MB 一般为GB
性能 接近原生 较弱
系统支持量 单机支持上千个容器 一般几十个

Docker包括三个基本概念:

镜像(Image)、容器(Container)、仓库(Repository)
理解了这三个概念,就理解了Docker的整个生命周期

镜像(Image)

我们都知道,操作系统分为内核和用户空间。对于Linux而言,内核启动后,会挂载root文件系统为其提供用户空间支持。而Docker镜像(lmage),就相当于是一个root文件系统。比如官方镜像centos:7.6就包含了完整的一套centos7,6最小系统的root文件系统。
Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变

容器(Container)

镜像(Image)和容器(Container)的关系,就像Java中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等

前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失

三、Registry

Registry在构建自动化平台,起着非常重要的作用!

仓库(Repository)

镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,DockerRegistry就是这样的服务

一个DockerRegistry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签

以centos镜像为例,centos是仓库的名字,其内包含有不同的版本标签,如,6.9、7.5。我们可以通过centos:6.9,或者centos:7.5来具体指定所需哪个版本的镜像。如果忽略了标签,比如centos,那将视为centos:latest

仓库名经常以两段式路径形式出现,比如study/ngin,前者往往意味着Docker Registry多用户环境下的用户名,后者则往往是对应的赖件名。但这并非绝对,取决于所使用的具体Docker Registry的软件或服务

Docker Registry 公开仓库

常用的Registry是官方的DockerHub,这也是默认的Registry。除此以外,还有CoreOS的Quay.io,CoreOS相关的镜像存储在这里;Google的Google Container Registry,Kubernetes的镜像使用用的就是这个服务
国内的一些云服务商提供了针对Docker Hub的镜像服务,这些镜像服务被称为加速器。常见的有阿里云加速器、DaoCloud加速器等。使用加速器会直接从国内的地址下载DockerHub的镜像,比直接从DockerHub下载速度会提高很多

国内也有一些云服务商提供类似于DockerHub的公开服务。比如网易云镜像服务、DaoCloud镜像市场丶阿里云镜像库等。

私有Docker Registry

除了使用公开服务外,用户还可以在本地搭建私有DockerRegistryoDocker官方提供了DockerRegistry镜像,可以直接使用做为私有Registry服务

开源的DockerRegistry镜像只提供了Docker Registry API的服务端实现,足以支持docker命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。在官方的商业化版本DockerTrustedRegistry中,提供了这些高级功能

除了官方的DockerRegistry外,还有第三方软件实现了DockerRegistryAPl,甚至提供了用户界面以及一些高级功能。比如,VMWare Harbor和Sonatype Nexus

Docker容器启动速度非常快,体现在2个方面;

  1. 磁盘占用空间小,因为docker镜像采用了分层技术,构建的镜像大小,只有自身的大小,不包含父镜像的大小
  2. 内存消耗少,docker容器共享的宿主机的内核,没有操作的进程消耗

什么是Dockerfile?

Dockerfile是自动构建docker镜像的配置文件,Dockerfile中的命令非常类似linux shell下的命令
Dockerfile,可以让用户自定义构建docker镜像,支持以 # 开头的注释行
一般,Dockerfile分为4部分
基础镜像(父镜像)信息
维护者信息
镜像操作命令
容器启动命令

当把Dockerfile存放到git仓库中,并为每个项目创建git仓库,这样操作通过自动化平台,可以自动构建docker镜像

dockerfile示例

###基础镜像csphere/centos:7.1
#
# MAINTAINER        liao
# DOCKER-VERSION    1.6.2
#
# Dockerizing CentOS7: Dockerfile for building CentOS images
#
FROM       centos:centos7.1.1503
MAINTAINER liao
ENV TZ "Asia/Shanghai"
ENV TERM xterm

ADD aliyun-mirror.repo /etc/yum.repos.d/CentOS-Base.repo
ADD aliyun-epel.repo /etc/yum.repos.d/epel.repo

RUN yum install -y curl wget tar bzip2 unzip vim-enhanced passwd sudo yum-utils hostname net-tools rsync man && \
    yum install -y gcc gcc-c++ git make automake cmake patch logrotate python-devel libpng-devel libjpeg-devel && \
    yum install -y --enablerepo=epel pwgen python-pip && \
    yum clean all

RUN pip install supervisor
ADD supervisord.conf /etc/supervisord.conf

RUN mkdir -p /etc/supervisor.conf.d && \
    mkdir -p /var/log/supervisor
    
EXPOSE 22

ENTRYPOINT ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisord.conf"]

Dockerfile解释

FROM centos:centos7.1.1503

基于父镜像构建其他docker镜像,父镜像:可以通过docker pull 命令获得,也可以自己制作

MAINTAINER liao

Dockerfile 维护者

ENV TZ "Asia/Shanghai"

ENV(environment)设置环境变量,一个Dockerfile中可以写多个。以上例子是:设置docker容器的时区为Shanghai

Dockerfile中有2条指令可以拷贝文件

ADD aliyun-mirror.repo /etc/yum.repos.d/CentOS-Base.repo

拷贝本地文件到docker容器里,还可以拷贝URL链接地址下的文件,ADD还具有解压软件包的功能(支持gzip, bzip2 or xz)

COPY test /mydir

拷贝本地文件到docker容器

RUN yum install -y curl wget....

RUN命令,非常类似linux下的shell命令 (the command is run in a shell - /bin/sh -c - shell form)
在Dockerfile中每执行一条指令(ENV、ADD、RUN等命令),都会生成一个docker image layer

RUN pip install supervisor

supervisor进程管理系统,推荐使用

ADD supervisord.conf /etc/supervisord.conf

添加supervisor的主配置文件,到docker容器里

RUN mkdir -p /etc/supervisor.conf.d

创建存放启动其他服务"supervisor.conf"的目录,此目录下的所有以.conf结尾的文件,在启动docker容器的时候会被加载

EXPOSE 22

端口映射 EXPOSE <host_port>:<container_port>

推荐使用docker run -p <host_port>:<container_port> 来固化端口

ENTRYPOINT ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisord.conf"]

一个Dockerfile中只有最后一条ENTRYPOINT生效,并且每次启动docker容器,都会执行ENTRYPOINT

以上文件就是用来生成第一个docker镜像的Dockerfile,通过docker build指令来生成docker镜像

docker build -t csphere/centos:7.1 .

如果Dockerfile在当前目录下,输入点.就可以进行加载当前目录下的Dockerfile

如果不在当前目录下需要运行docker build -t csphere/centos:7.1 <Dockerfile_dir>加载相对路径下的Dockerfile

docker镜像的命名规则 registry_url/namespace/image_name:tag 默认tag是latest

在构建Docker镜像时,如果有自己内部的yum源,替换成自己内部的yum源地址,可以加快构建速度。

如果第一次构建失败,会有部分镜像layer生成,第二次构建会基于第一次构建所生成的layer(use cache),继续构建

Step 10 : EXPOSE 22
—> Running in 0ed1c5479ebc
—> c57a5bac41c8
Removing intermediate container 0ed1c5479ebc
Step 11 : ENTRYPOINT /usr/bin/supervisord -n -c /etc/supervisord.conf
—> Running in e16c7ac2fd45
—> 185ef7b101a8
Removing intermediate container e16c7ac2fd45
Successfully built 185ef7b101a8
可以看到每执行一条Dockerfile的指令都会生成一个镜像的layerc57a5bac41c8 185ef7b101a8 最后185ef7b101a8这个是docker镜像的ID,185ef7b101a8是由c57a5bac41c8 185ef7b101a8…layers叠加而成,体现了docker镜像是分层的

docker images  # 查看当前主机本地有哪些docker镜像 

REPOSITORY                             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
csphere/centos                         7.1                 185ef7b101a8        40 minutes ago      451.9 MB

通过docker镜像生成一个docker容器

docker help run #查看docker run命令的使用方法

介绍日常工作中经常用到的参数:

docker run -it #启动docker容器在前端 docker run -d #启动docker容器在后台
docker run -p docker run -P

在Dockerfile中有一条指令是EXPOSE 22,如果使用-P,宿主机会随机选择一个没有被使用的端口和docker容器的22端口做端口映射,如果docker主机或者容器重启后,宿主机又会随机选择一个没有被使用的端口和docker容器的22端口做端口映射,这样端口会发生变化
如果使用-p,比如2222:22,这样不管是docker主机或者容器重启后,2222:22端口都是这样来映射,不会发生改变
生成docker容器

docker run -d -p 2222:22 --name base csphere/centos:7.1
>>>37ac69acf47d501ffc61d8883ae2ba362a132d11e46897212a92b1936e0a0593

参数说明:
-d 后台运行
-it 前台交互式运行
-P 22 将宿主机的一个未使用的随机端口映射到容器的22端口
-p 2222:22 将宿主机的2222端口映射到容器的22端口
–name base 给容器命名为base
csphere/centos:7.1 使用这个镜像镜像创建docker容器
查看Docker容器

docker ps

ps默认只会显示容器在“running”的状态的,容器列表

docker ps -a

ps -a 会查看到所有的容器列表

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章