Docker虚拟化

1. Docker虚拟化特点

跟传统VM比较具有如下优点:

  • 操作启动快

运行时的性能可以获取极大提升,管理操作(启动,停止,开始,重启等等) 都是以秒或毫秒为单位的。

  • 轻量级虚拟化

你会拥有足够的“操作系统”,仅需添加或减小镜像即可。在一台服务器上可以布署100~1000个Containers容器。但是传统虚拟化,你虚拟10-20个虚拟机就不错了。

  • 开源免费

开源的,免费的,低成本的。由现代Linux内核支持并驱动。注* 轻量的Container必定可以在一个物理机上开启更多“容器”,注定比VMs要便宜。

2. 为什么使用docker

Docker 在如下几个方面具有较大的优势:

  • 更快速的交付和部署

Docker在整个开发周期都可以完美的辅助你实现快速交付。Docker允许开发者在装有应用和服务本地容器做开发。可以直接集成到可持续开发流程中。

开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。

  • 高效的部署和扩容

Docker容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。

Docker的兼容性和轻量特性可以很轻松的实现负载的动态管理。你可以快速扩容或方便的下线的你的应用和服务,这种速度趋近实时。

  • 更高的资源利用率

Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。

  • 更简单的管理

使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。

3. Docker镜像原理

一个完整的Docker镜像可以支撑一个Docker容器的运行,在Docker容器运行过程中主要提供文件系统数据支撑。

Docker镜像作为docker中最基本的概念,有以下几个特性:

  • 镜像分层,每个镜像都由一个或多个镜像层组成;
  • 可通过在某个镜像加上一定的镜像层得到新镜像(此过程可通过编写dockerfile或基于容器Commit实现);
  • 每个镜像层拥有唯一镜像ID;
  • 镜像在存储和使用时共享相同的镜像层(根据ID),所以在pull镜像时,已有的镜像层会自动跳过下载;
  • 每个镜像层都是只读,即使启动成容器,也无法对其真正的修改,修改只会作用于最上层的容器层;

Docker容器,可以理解为一个或多个运行进程,而这些运行进程将占有相应的内存,相应的CPU计算资源,相应的虚拟网络设备以及相应的文件系统资源。而Docker容器所占用的文件系统资源,则通过Docker镜像的镜像层文件来提供。

基于每个镜像的json文件,Docker可以通过解析Docker镜像的json的文件,获知应该在这个镜像之上运行什么样的进程,应该为进程配置怎么样的环境变量,Docker守护进程实现了静态向动态的转变。

4. Docker安装配

CentOS7.x Linux,基于YUM二进制方式,操作命令如下:

#安装第三方Epel-relase扩展源;

yum install epel-release -y

#安装Docker软件包程序;

yum install docker -y

#查看Docker软件包是否部署;

yum list docker

rpm -qa|grep -w docker

#启动Docker Engine服务;

systemctl start docker.service

#查看Docker版本信息;

docker version

 
根据如上Docker部署方法,Docker虚拟化平台构建完成,如图所示:

5. Docker仓库源更新实战

Docker默认连接的国外官方镜像,通常根据网络情况不同,访问时快时慢,大多时候获取速度非常慢,为了提示效率可以自建仓库或者先修改为国内仓库源,提升拉取镜像的速度。

Docker可以配置的国内镜像有很多可供选择,例如:Docker中国区官方镜像、阿里云、网易蜂巢、DaoCloud等,这些都是国内比较快的镜像仓库。

从国外官网下载Docker Tomcat镜像,访问速度慢,

Docker镜像修改方法,vim /etc/docker/daemon.json,执行如下命令即可:

cat>/etc/docker/daemon.json<<EOF
{

"registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com"]

}

EOF

service docker restart

systemctl start docker.service

重启Docker服务即可,修改仓库地址为国内仓库后,获取镜像速度非常快。

6. Docker常用命令讲解

Docker常用命令详解:

docker  version #查看版本

docker  search centos #搜索可用docker镜像

docker  images 查看当前docker所有镜像

docker  pull  centos #下载镜像

cat   centos.tar | docker import  -  centos6  #Docker导入镜像

docker  export  容器id  > cenos6.tar  #Docker导出镜像

docker  run   centos echo "hello word"  #docker容器中运行hello world!

docker  run  centos yum install ntpdate   #在容器中安装ntpdate的程序

docker  ps -l 命令获得最后一个容器的id

docker   ps  -a查看所有的容器。

运行docker commit 提交刚修改的容器,例如:

docker  commit  2313132(容器的id  centos:v1

docker run -it -d  --privileged  --name docker-web centos /bin/bash 生成一个新的/bin/bash shell环境的容器,可以登录进入操作,其中-t 表示打开一个终端的意思,-i表示可以交互输入,--name 表示容器的名字, --privileged表示特权较高可以mount并容器里面启动容器

docker exec -it  id  /bin/bash  进入容器里面

docker  run  -d  centos:v1  /bin/bash  ,-d表示在后台启动,以daemon方式启动。  

docker stop  id 关闭容器

docker start  id 启动某个容器

docker  rm  id 删除容器,docker  rmi  images删除镜像

docker  run  -d  -p 80:80   centos:v2,解析:-p指定容器启动后docker上运行的端口映射及容器里运行的端口,80:80,第一个80表示docker系统上的80,第二个80表示docker虚拟机里面的端口。用户默认访问本机80端口,自动映射到容器里面的80端口。

Docker命令表格如下:

docker

search

在docker hub中搜索镜像;

docker

pull

从docker镜像源服务器拉取指定镜像或者库镜像;

docker

push

推送指定镜像或者库镜像至docker源服务器;

docker

history

展示一个镜像形成历史;

docker

images

列出系统当前镜像;

docker

run

创建一个新的容器并运行一个命令;

docker

start

启动容器;

docker

stop

停止容器;

docker

attach

当前shell下attach连接指定运行镜像;

docker

build

通过Dockerfile定制镜像;

docker

commit

提交当前容器为新的镜像;

docker

cp

从容器中拷贝指定文件或者目录到宿主机中;

docker

create

创建一个新的容器,同run,但不启动容器;

docker

diff

查看docker容器变化;

docker

events

从docker服务获取容器实时事件;

docker

exec

在已存在的容器上运行命令;

docker

export

导出容器的内容流作为一个tar归档文件[对应import];

docker

import

从tar包中的内容创建一个新的文件系统映像[对应export];

docker

info

显示系统相关信息;

docker

inspect

查看容器详细信息;

docker

kill

指定docker容器;

docker

load

从一个tar包中加载一个镜像[对应save];

docker

login

注册或者登陆一个docker源服务器;

docker

logout

Docker registry退出;

docker

logs

输出当前容器日志信息;

docker

port

查看映射端口对应的容器内部源端口;

docker

pause

暂停容器;

docker

ps

列出容器列表;

docker

restart

重启运行的容器;

docker

rm

移除一个或者多个容器;

docker

rmi

移除一个或多个镜像;

docker

save

保存一个镜像为一个tar包[对应load];

docker

tag

给源中镜像打标签,修改镜像名称;

docker

top

查看容器中运行的进程信息;

docker

unpause

取消暂停容器;

docker

version

查看docker版本号;

docker

wait

截取容器停止时的退出状态值。

7. Docker虚拟化平台的案例

1)根据如上的Docker部署指令,Docker虚拟化平台构建完成,作为运维人员如何在企业中应用好Docker软件呢?能够使用Docker虚拟化平台实现哪些企业需求呢?Docker虚拟化技术的产物是Docker容器(虚拟机)。
2)要掌握Docker虚拟化技术,首先要了解3个Docker虚拟化相关的概念:
  •  Docker镜像
Docker镜像类似Linux ISO镜像文件,主要是存储了各种应用程序、软件服务、各种数据等,为Docker虚拟化的产物(虚拟机)提供数据支撑的,后续的虚拟机所需的文件、数据都是从镜像文件中获取的,而且Docker镜像内容只读的、不能被修改的、模板数据。
  • Docker容器(虚拟机)
Docker容器(虚拟机)是基于Docker镜像运行之后的实例,类似进程和程序的关系(进程是程序运行之后的实例),Docker容器是可读、可写的,不能直接修改镜像的数据内容,镜像是持续为容器提供服务,没有镜像就没有容器,容器永远离不开镜像。
  •  Docker仓库
Docker仓库是用于存储镜像的地方,仓库通常分为两类:公共仓库、私有仓库,企业测试环境、生产环境推荐自建私有仓库,私有仓库:安全、稳定、高效、管理、定制性。
 
3)基于Docker虚拟化平台,构建一套Nginx WEB服务器(容器),同时让NginxWEB服务器对外提供WEB服务,用户通过浏览器可以实现页面的访问,操作步骤如下:
#在Docker仓库中搜索Nginx镜像;
docker search nginx
 
#从Docker仓库下载Nginx镜像;
docker pull docker.io/nginx
#查看本地Nginx镜像列表;
docker images|grep -i nginx
 
#基于本地Nginx镜像启动Nginx WEB服务(容器|虚拟机);
docker run -itd -p 80:80 docker.io/nginx
    Run,全新启动一台容器(虚拟机);
  • -i,interactive交互模式;
  • -t,tty打开一个终端;
  • -d,daemon后台启动;
  • -p,开启DNAT映射,将宿主机80映射至容器的80,用户访问宿主机的80即是访问容器的80。
#查看已经启动的Nginx虚拟机(容器);
  • docker ps

#访问Nginx容器中的WEB服务;

#查看虚拟机(容器)的IP地址;

docker inspect 3d5559023d71|grep -i ipaddr|tail -1|awk -F\" '{print $4}'

#将宿主机的index.html文件部署至Nginx容器(虚拟机)中;

docker cp index.html 3d5559023d71:/usr/share/nginx/html/

8.WEB平台管理&镜像管理

Docker WEB管理

通常来讲,开发人员和管理人员默认通过命令行来创建及运行Docker容器,但Docker的Remote API让他们可以通过充分利用REST(代表性状态传输协议)的API,运行相同的命令。Docker UI也是基于API方式管理宿主机的Docker引擎。Docker UI Web前端程序让你可以处理通常通过Web浏览器的命令行来管理的许多任务。主机上的所有容器都可以通过仅仅一条连接来处理,该项目几乎没有任何依赖关系。该软件目前仍在大力开发之中,但是它采用麻省理工学院(MIT)许可证,所以可以免费地重复使用。

Docker UI不包含任何内置的身份验证或安全机制,所以务必将任何公之于众的DockerUI连接放在用密码来保护的系统后面。

1)下载Docker UI镜像;

只需要在宿主机pull相关的镜像即可,指令如下:

docker pull uifd/ui-for-docker

docker images

 

2)启动docker-UI服务,并且映射9000至容器9000;

docker run -it -d --name docker-web -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock docker.io/uifd/ui-for-docker

如果启动Docker端口映射,报错信息如下:

docker0: iptables: No chain/target/match by that name.

解决方法:

如上报错信息是因为本地iptables规则策略没有匹配的链表,解决方案如下:

pkill docker

iptables -t nat -F

ifconfig docker0 down

yum install -y bridge* -y

brctl delbr docker0

service docker restart

宿主机访问:9000端口

 

管理启动,停止容器实例

 

3)Docker 镜像管理Commit(完整导出)

#将修改的新容器提交为新镜像;

docker commit f43cc8b041d0

#默认会提交到images列表中;

docker images

#默认提交的镜像名称是None,可以修改镜像名称;

docker tag b95ad546e113 nginx2


4)Docker 镜像管理Export|Import(导出丢失内存中数据)

#将修改的新容器提交为新镜像;docker export c16d454849b6 >centos-v2.tar

#默认不会提交到images列表中,而是在当前目录;

ls -l centos-v2.tar

#如果将导出tar镜像文件,导入镜像列表&可以加上名称;

cat centos-v2.tar |docker import -

cat centos-v2.tar |docker import - centos:v2

5)Docker 镜像管理Load|Save(主要是针对镜像|完整导出)

#导入images列表中的镜像为tar文件;

docker save centos:v1 >centos-v3.tar

#导入tar文件至镜像列表&默认无需修改名称;

docker load < centos-v3.tar

9.Docker网络剖析&Pipework网络

基于Docker run创建Docker容器时,可以使用--net选项指定容器的网络模式,Docker默认有以下四种网络模式:

  • host模式,使用--net=host指定;
  • container模式,使用--net=container:NAME_or_ID指定;
  • none模式,使用--net=none指定;,
  • bridge模式,使用--net=bridge指定,默认设置;

1) Host模式详解:

默认Docker容器运行会分配独立的Network Namespace隔离子系统,基于host模式,容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace,容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。

2) Container模式详解:

熟悉了host模式,Container模式也非常好理解,Container模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。

即新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样两个容器除了网络方面相同之外,其他的如文件系统、进程列表等还是隔离的。

3) None模式详解:

None模式与其他的模式都不同,如果处于None模式,Docker容器拥有自己的Network Namespace,但是并不为Docker容器进行任何网络配置。也就是说该Docker容器没有网卡、IP、路由等信息,需要手工为Docker容器添加网卡、配置IP等,典型Pipework工具为Docker容器指定IP等信息;

4) Bridge桥接模式

Bridge模式是Docker默认的网络模式,该模式会为每一个容器分配Network Namespace、设置IP、路由等配置,默认会将Docker容器连接到一个虚拟网桥交换机Docker0上。

Docker Bridge创建过程:

1) 首先宿主机上创建一对虚拟网卡veth pair设备,veth设备总是成对出现的,组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来,veth设备常用来连接两个网络设备。

2) Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0,然后将另一端放在宿主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show命令查看。

3) 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。

4) 此时容器IP与宿主机能够通信,宿主机也可以访问容器中的IP地址,在Bridge模式下,连在同一网桥上的容器之间可以相互通信,同时容器也可以访问外网,但是其他物理机不能访问docker容器IP,需要通过NAT将容器IP的port映射为宿主机的IP和port。

Bridge自定义桥接br0:

基于CentOS7.x构建Docker桥接网络,案例方法如下:

配置bridge桥接网络可以直接设置网卡配置文件:

/etc/sysconfig/network-scripts/下,修改ifcfg-ens32网卡配置,同时增加ifcfg-br0桥接网卡配置,操作流程如下:

#宿主机ens32网卡内容:
cat /etc/sysconfig/network-scripts/ifcfg-ens33

DEVICE=ens32

BOOTPROTO=static

ONBOOT=yes

TYPE=Ethernet

BRIDGE="br0"

IPADDR=192.168.86.128

NETMASK=255.255.255.0

GATEWAY=192.168.86.2

#宿主机br0网卡内容:
cat /etc/sysconfig/network-scripts/ifcfg-br0

DEVICE="br0"

BOOTPROTO=static

ONBOOT=yes

TYPE="Bridge"

IPADDR=192.168.86.128

NETMASK=255.255.255.0

GATEWAY=192.168.86.2

重启网卡并启动docker服务即可;

service network restart

systemctl daemon-reload

systemctl restart docker.service

 Docker默认提供了一个隔离的内网环境,启动时会建立一个docker0的虚拟网卡,每个容器都是连接到docker0网卡上的。而docker0的ip段为172.17.0.1,如果想让容器与宿主机同一网段的其他机器访问,就必须在启动docker的时候将某个端口映射到宿主机的端口。

KVM的桥接网络非常方便,其实docker也比较方便,至少不是自带的桥接而已,今天我们来讲解centos7下如果快速实现docker容器桥接网络,并为容器分配外网IP。如下为通过pipework工具配置容器IP方法:

安装pipework

git clone https://github.com/jpetazzo/pipework

cp ~/pipework/pipework /usr/local/bin/

下载centos镜像启动容器并设置网络

docker pull docker.io/jdeathe/centos-ssh

docker tag docker.io/jdeathe/centos-ssh centos-ssh (修改镜像别名)

docker run -itd --privileged --net=none --name=ssh_86.131 centos-ssh /bin/bash

pipework  br0  centos-ssh  192.168.86.131/24@192.168.86.2(@后面是bro网卡)

进入容器查看ip

docker exec -it 8dec649772d4 /bin/bash   


 

10.Docker仓库构建&仓库管理

1)Docker虚拟化技术的底层支撑是Docker镜像,没有Docker镜像,就不会存在Docker容器,Docker容器所需的数据可以从镜像中读取的。Docker镜像存储在Docker仓库中的,仓库分为两种:
  • Docker公共仓库:零配置、公共的、相对稳定、不安全、速度比较慢;
  • Docker私有仓库:手工配置、私有、很稳定、安全、速度非常快。
2)下载Docker registry镜像,命令如下:
docker pull docker.io/registry
3)启动私有仓库容器,启动命令如下:

mkdir -p  /data/registry/

docker run -itd  -p  5000:5000 -v /data/registry:/var/lib/registry  docker.io/registry

Docker本地仓库启动后台容器启动,如图所示:

 

4)将本地镜像上传至Docker仓库中,命令操作如下;

for i in `docker images |awk 'NR>1 {print $1":"$2}'`;do echo $i ;done

for i in `docker images |awk 'NR>1 {print $1":"$2}'`;do docker tag $i localhost:5000/$i ;docker push localhost:5000/$i;done

5)客户端上传镜像至本地私有仓库,如下以busybox镜像为例,将busybox上传至私有仓库服务器。 

docker pull busybox

docker tag busybox 192.168.86.128:5000/busybox

docker push 192.168.86.128/busybox

6)检测本地私有仓库:

curl -XGET http://192.168.86.128:5000/v2/_catalog

curl -XGET http://192.168.86.128:5000/v2/busybox/tags/list

7)客户端使用本地私有仓库:
客户端docker配置文件vim /etc/sysconfig/docker添加如下代码,同时重启docker服务,获取本地私有仓库如图所示:

OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false --insecure-registry 192.168.86.128:5000'

ADD_REGISTRY='--add-registry 192.168.86.128:5000'

至此,docker本地私有仓库部署完毕,可以向仓库中添加或者更新Docker镜像。

11.Dockerfile企业案例

由于Docker官网公共仓库镜像大多不完整,无法真正满足企业的生产环境系统,此时需要我们自行定制镜像或者重新打包镜像。Docker镜像制作是管理员的必备工作之一,Docker镜像制作的方
法主要有两种,制作方法如下:
  • Docker commit|export将新容器提交至Images列表;
  • 编写Dockerfile,bulid新的镜像至镜像列表;

1. Dockerfile语法命令详解一

企业生产环境推荐使用Dockerfile制作镜像,Dockerfile制作原理:将基于一个基础镜像,通过编写Dockerfile方式,将各个功能进行叠加,最终形成新的Docker镜像,是目前互联网企业中打包镜像最为推荐的方式。Dockerfile是一个镜像的表示,也是一个镜像的原材料,可以通过Dockerfile来描述构建镜像,并自动构建一个容器。
如下为DockerFile制作镜像,必备的指令和参数的详解:

FROM  指定所创建镜像的基础镜像;

MAINTAINER 指定维护者信息;

RUN 运行命令;

CMD 指定启动容器时默认执行的命令;

LABEL 指定生成镜像的元数据标签信息;

EXPOSE 声明镜像内服务所监听的端口;

ENV 指定环境变量;

ADD 赋值指定的<src>路径下的内容到容器中的<dest>路径下,<src>可以为URL;如果为tar文件,会自动解压到<dest>路径下

COPY 赋值本地主机的<scr>路径下的内容到容器中的<dest>路径下;一般情况下推荐使用COPY而不是ADD;

ENTRYPOINT 指定镜像的默认入口;

VOLUME 创建数据挂载点;

USER 指定运行容器时的用户名或UID;

WORKDIR 配置工作目录;

ARG 指定镜像内使用的参数(例如版本号信息等);

ONBUILD 配置当前所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作的命令;

STOPSIGNAL 容器退出的信号;

HEALTHCHECK  如何进行健康检查;

SHELL 指定使用SHELL时的默认SHELL类型;

2. Dockerfile语法命令详解二

FROM指定所创建的镜像的基础镜像,如果本地不存在,则默认会去Docker Hub下载指定镜像。

格式为:FROM<image>,或FROM<image>:<tag>,或FROM<image>@<digest>。任何Dockerfile中的第一条指令必须为FROM指令。并且,如果在同一个Dockerfile文件中创建多个镜像,可以使用多个FROM指令(每个镜像一次)。

MAINTAINER指定维护者信息,格式为MAINTAINER<name>。例如:MAINTAINER image_creator@docker.com 

该信息将会写入生成镜像的Author属性域中。

RUN运行指定命令。

格式为:RUN<command>或RUN ["executable","param1","param2"]。

注意:后一个指令会被解析为json数组,所以必须使用双引号。

前者默认将在shell终端中运行命令,即/bin/sh -c;后者则使用exec执行,不会启动shell环境。

指定使用其他终端类型可以通过第二种方式实现,例如:

RUN ["/bin/bash","-c","echo hello"]

每条RUN指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用\换行。例如:

RUN apt-get update \

&& apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \

&& rm -rf /var/cache/apt

CMD用来指定启动容器时默认执行的命令。它支持三种格式:

CMD ["executable","param1","param2"] 使用exec执行,是推荐使用的方式;

CMD param1 param2 在/bin/sh中执行,提供给需要交互的应用;

CMD ["param1","param2"] 提供给ENTRYPOINT的默认参数。

每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行。入股用户启动容器时指定了运行的命令(作为run的参数),则会覆盖掉CMD指定的命令。

LABEL指令用来生成用于生成镜像的元数据的标签信息。

格式为:LABEL <key>=<value> <key>=<value> <key>=<value> ...。

例如:

LABEL version="1.0"

LABEL description="This text illustrates \ that label-values can span multiple lines."

EXPOSE声明镜像内服务所监听的端口。

格式为:EXPOSE <port> [<port>...]

例如:

EXPOSE 22 80 443 3306

注意:该命令只是起到声明作用,并不会自动完成端口映射。在容器启动时需要使用-P(大写P),Docker主机会自动分配一个宿主机未被使用的临时端口转发到指定的端口;使用-p(小写p),则可以具体指定哪个宿主机的本地端口映射过来。

ENV指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在。

格式为:ENV <key><value>或ENV<key>=<value>...。

例如:

ENV GOLANG_VERSION 1.6.3

ENV GOLANG_DOWNLOAD_RUL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz

ENV GOLANG_DOWNLOAD_SHA256 cdd5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb

RUN curl -fssL "$GOLANG_DOWNLOAD_RUL" -o golang.tar.gz && echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && tar -C /usr/local -xzf golang.tar.gz && rm golang.tar.gz

ENV GOPATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/bin" && chmod -R 777 "$GOPATH"

指令指定的环境变量在运行时可以被覆盖掉,如docker run --env <key>=<value> built_image。

ADD该指令将复制指定的<src>路径下的内容到容器中的<dest>路径下。

格式为:ADD<src> <dest>

其中<src>可以使Dockerfile所在目录的一个相对路径(文件或目录),也可以是一个URL,还可以是一个tar文件(如果是tar文件,会自动解压到<dest>路径下)。<dest>可以使镜像内的绝对路径,或者相当于工作目录(WORKDIR)的相对路径。路径支持正则表达式,例如:

ADD *.c /code/

COPY复制本地主机的<src>(为Dockerfile所在目录的一个相对路径、文件或目录)下的内容到镜像中的<dest>下。目标路径不存在时,会自动创建。路径同样支持正则。格式为:COPY <src> <dest>当使用本地目录为源目录时,推荐使用COPY。

ENTRYPOINT指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。

支持两种格式:

ENTRYPOINT ["executable","param1","param2"] (exec调用执行);

ENTRYPOINT command param1 param2(shell中执行)。

此时,CMD指令指定值将作为根命令的参数。

每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个有效。

在运行时可以被--entrypoint参数覆盖掉,如docker run --entrypoint。

VOLUME

创建一个数据卷挂载点。

格式为:VOLUME ["/data"]

可以从本地主机或者其他容器挂载数据卷,一般用来存放数据库和需要保存的数据等。

USER

指定运行容器时的用户名或UID,后续的RUN等指令也会使用特定的用户身份。格式为:USER daemon

当服务不需要管理员权限时,可以通过该指令指定运行用户,并且可以在之前创建所需要的用户。例如:

RUN groupadd -r nginx && useradd -r -g nginx nginx要临时获取管理员权限可以用gosu或者sudo。

WORKDIR为后续的RUN、CMD和ENTRYPOINT指令配置工作目录。

格式为:WORKDIR /path/to/workdir。

可以使用多个WORKDIR指令,后续命令如果参数是相对的,则会基于之前命令指定的路径。例如:

WORKDIR /a

WORKDIR b

WORKDIR c

RUN pwd

则最终路径为/a/b/c

ARG指定一些镜像内使用的参数(例如版本号信息等),这些参数在执行docker build命令时才以--build-arg<varname>=<value>格式传入。格式为:ARG<name>[=<default value>]。

则可以用docker build --build-arg<name>=<value>来指定参数值。

ONBUILD

配置当所创建的镜像作为其他镜像的基础镜像的时候,所执行创建操作指令。

格式为:ONBUILD [INSTRUCTION]。

例如Dockerfile使用如下的内容创建了镜像image-A:

[...]

ONBUILD ADD . /app/src

ONBUILD RUN /usr/local/bin/python-build --dir /app/src

[...]

如果基于image-A镜像创建新的镜像时,新的Dockerfile中使用FROM image-A指定基础镜像,会自动执行ONBUILD指令的内容,等价于在后面添加了两条指令:

FROM image-A

# Automatically run the following

ONBUILD ADD . /app/src

ONBUILD RUN /usr/local/bin/python-build --dir /app/src

使用ONBUILD指令的镜像,推荐在标签中注明,例如:ruby:1.9-onbuild。

STOPSIGNAL

指定所创建镜像启动的容器接收退出的信号值。例如:

STOPSIGNAL singnal

HEALTHCHECK配置所启动容器如何进行健康检查(如何判断是否健康),自Docker 1.12开始支持。格式有两种:

HEALTHCHECK [OPTIONS] CMD command    :根据所执行命令返回值是否为0判断;HEALTHCHECK NONE:禁止基础镜像中的健康检查。

 [OPTION]支持:

--inerval=DURATION  (默认为:30s):多久检查一次;

--timeout=DURATION  (默认为:30s):每次检查等待结果的超时时间;

--retries=N        (默认为:3):如果失败了,重试几次才最终确定失败。

SHELL指定其他命令使用shell时的默认shell类型。

格式为: SHELL ["executable","parameters"]默认值为 ["bin/sh","-c"]。

注意:对于Windows系统,建议在Dockerfile开头添加# escape=`来指定转移信息。

创建镜像

编写Dockerfile之后,可以通过docker build命令来创建镜像。

基本的docker build [选项] 内容路径,该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下的所有内容发送给Docker服务端,由服务端来创建镜像。因此除非生成镜像需要,否则一般建议放置Dockerfile的目录为空目录。

如果使用非内容路径下的Dockerfile,可以通过-f选项来指定其路径;

要指定生成镜像的标签信息,可以使用-t选项。

例如:指定Dockerfile所在路径为 /tmp/docker_builder/,并且希望生成镜像标签为build_repo/first_image,可以使用下面的命令:

docker build -t build_repo/first_image /tmp/docker_builder

使用.dockerignore文件

可以通过.dockeringore文件(每一行添加一条匹配模式)来让Docker忽略匹配模式路径下的目录和文件。例如:

# comment

*/tmp*

*/*/tmp*

tmp?

~*

3.Dockerfile制作规范及技巧

从企业需求出发,定制适合自己需求、高效方便的镜像,可以参考官方Dockerfile文件,也可以根据自身的需求,逐步的完善,在构建中不断优化Dockerfile文件;

Dockerfile制作镜像规范和技巧如下:

  • 精简镜像用途:尽量让每个镜像的用途都比较集中、单一,避免构造大而复杂、多功能的镜像;
  • 选用合适的基础镜像:过大的基础镜像会造成构建出臃肿的镜像,一般推荐比较小巧的镜像作为基础镜像;
  • 提供详细的注释和维护者信息: Dockerfile也是一种代码,需要考虑方便后续扩展和他人使用;
  • 正确使用版本号:使用明确的具体数字信息的版本号信息,而非latest,可以避免无法确认具体版本号,统一环境;
  • 减少镜像层数:减少镜像层数建议尽量合并RUN指令,可以将多条RUN指令的内容通过&&连接;
  • 及时删除临时和缓存文件:这样可以避免构造的镜像过于臃肿,并且这些缓存文件并没有实际用途;
  • 提高生产速度:合理使用缓存、减少目录下的使用文件,使用.dockeringore文件等;
  • 调整合理的指令顺序:在开启缓存的情况下,内容不变的指令尽量放在前面,这样可以提高指令的复用性;
  • 减少外部源的干扰:如果确实要从外部引入数据,需要制定持久的地址,并带有版本信息,让他人可以重复使用而不出错。

4.DockerFile企业案例一

DockerFile企业案例一,将启动Docker容器,同时开启Docker容器对外的22端口的监听,实现通过CRT或者Xshell登录:

#进入容器

docker exec -it 85aa1a867c3f /bin/bash

rpm --rebuilddb && yum  install  pam  cracklib-dicts -y

[root@5255b18871ae /]# echo '123456' | passwd --stdin root

Changing password for user root.

passwd: all authentication tokens updated successfully.

我们如果现在启动sshdsshd会报错:

Could not load host key: /etc/ssh/ssh_host_rsa_key

Could not load host key: /etc/ssh/ssh_host_ecdsa_key

Could not load host key: /etc/ssh/ssh_host_ed25519_key

所以我们先生成/etc/ssh/ssh_host_rsa_key/etc/ssh/ssh_host_ecdsa_key和/etc/ssh/ssh_host_ed25519_key

[root@85aa1a867c3f /]# ssh-keygen -q -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key -N ''

[root@85aa1a867c3f /]# ssh-keygen -q -t rsa -b 2048 -f /etc/ssh/ssh_host_ecdsa_key -N ''

[root@85aa1a867c3f /]# ssh-keygen -q -t rsa -b 2048 -f /etc/ssh/ssh_host_ed25519_key -N ''

然后查一下容器的IP启动sshd

[root@5255b18871ae /]# /usr/sbin/sshd 

我们看到容器IP192.168.1.3,从外部远程ssh到这个容器:

发现容器立即关闭了连接,原因是容器的ssh使用了pam_loginuid.so模块,我们把它关掉:

[root@5255b18871ae /]# sed -i '/^session\s\+required\s\+pam_loginuid.so/s/^/#/' /etc/pam.d/sshd

上述命令的意思是:在/etc/pam.d/sshd文件里注释掉"session    required     pam_loginuid.so"这一行。

然后重新启动sshd

[root@5255b18871ae /]# /usr/sbin/sshd 

再次尝试远程ssh登入:

[root@localhost ~]# ssh root@192.168.1.3

root@192.168.1.3's password:

Last login: Tue Dec  2 03:00:07 2014 from 192.168.1.3

[root@5255b18871ae ~]#

登录成功!

 Dockerfile文件方式制作如下:

Docker服务端创建Dockerfile文件,实现容器运行开启22端口,内容如下:

# 设置基本的镜像,后续命令都以这个镜像为基础

FROM centos

# 作者信息

MAINTAINER JFEDU.NET

# RUN命令会在上面指定的镜像里执行任何命令

RUN rpm --rebuilddb;yum install passwd openssl openssh-server -y

RUN echo '123456' | passwd --stdin root

RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700

/root/.ssh

RUN ssh-keygen -q -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key -N ''

RUN ssh-keygen -q -t rsa -b 2048 -f /etc/ssh/ssh_host_ecdsa_key -N ''

RUN ssh-keygen -q -t rsa -b 2048 -f /etc/ssh/ssh_host_ed25519_key -N ''

RUN sed -i '/^session\s\+required\s\+pam_loginuid.so/s/^/#/' /etc/pam.d/sshd

# 暴露ssh端口22

EXPOSE 22

# 设定运行镜像时的默认命令:输出ip,并以daemon方式启动sshd

CMD /usr/sbin/sshd;/bin/bash

基于Dockerfile来创建生成镜像,命令如下:

docker build根据Dockerfile创建镜像(centos:ssh)执行一下两步:

docker  build  -t  centos:ssh  -  <  Dockerfile

docker  build  -t  centos:ssh  .

5. DockerFile企业案例二

DockerFile企业案例二,开启SSH 6379端口,让Redis端口对外访问,Dockerfile内容如下:

# 设置基本的镜像,后续命令都以这个镜像为基础

FROM centos_lamp:v1

# 作者信息

MAINTAINER JFEDU.NET

# RUN命令会在上面指定的镜像里执行任何命令

RUN rpm --rebuilddb;yum install redis* -y

RUN sed -i '/bind/127.0.0.1/0.0.0.0/g' /etc/redis.conf

#暴露ssh端口6379

EXPOSE 6379

#设定运行以daemon方式启动sshd

CMD /usr/sbin/redis -D

6. DockerFile企业案例三

DockerFile企业案例三,基于Dockerfile开启Apache 80端口,并远程连接服务器,dockerfile内容如下:

# 设置基本的镜像,后续命令都以这个镜像为基础

FROM centos_lamp:v1

# 作者信息

MAINTAINER JFEDU.NET

# RUN命令会在上面指定的镜像里执行任何命令

RUN rpm --rebuilddb;yum install pcre-devel -y

RUN rpm --rebuilddb;yum install httpd httpd-devel –y

RUN echo “<h1>The Test Page JFEDU</h1>”

>>/var/www/html/index.html

#暴露ssh端口80

EXPOSE 80

#启动httpd

CMD service httpd start;/bin/bash

最终截图如下:

7. DockerFile企业案例四

DockerFile企业案例四,Docker虚拟化中,如何来构建我们的MYSQL数据库服务器呢?答案很简单,我们可以是dockerfile来生成mysql镜像并启动运行即可。

FROM centos:v1

RUN groupadd -r mysql && useradd -r -g mysql mysql

RUN rpm --rebuilddb;yum install -y gcc zlib-devel gd-devel

ENV MYSQL_MAJOR 5.6

ENV MYSQL_VERSION 5.6.20

RUN curl -SL "http://dev.mysql.com/get/Downloads/MySQL-$MYSQL_MAJOR/mysq l-$MYSQL_VERSION-linux-glibc2.5-x86_64.tar.gz" -o mysql.tar.gz \ && curl -SL "http://mysql.he.net/Downloads/MySQL-$MYSQL_MAJOR/mysql-$MY SQL_VERSION-linux-glibc2.5x86_64.tar.gz.asc" -o mysql.tar.gz.asc \ && mkdir /usr/local/mysql \ && tar -xzf mysql.tar.gz -C /usr/local/mysql \ && rm mysql.tar.gz* \

ENV PATH $PATH:/usr/local/mysql/bin:/usr/local/mysql/scripts

WORKDIR /usr/local/mysql

VOLUME /var/lib/mysql

EXPOSE 3306

CMD /usr/local/mysql/bin/mysqld_safe

12.Docker容器CPU&MEM&DISK资源扩容

1、Docker容器CPU&MEM资源扩容

1) Docker容器支持CPU、MEM、DISK的资源的配置的,默认配置的参数指令:

  • CPU配置:--cpuset-cpus=0-0;
  • MEM配置:-m 512m;

启动容器:

  • privileged:特权:允许执行mount等root执行的命令,还可以容器里面启动容器

docker run -itd --privileged --net=none --cpuset-cpus=0-1 -m 1024m --name=ssh_86.132 centos-ssh:v1 /bin/bash

2Docker容器Disk硬盘资源扩容一(Overlay2驱动方式) 

#查看docker默认驱动命令是docker info|egrep "Storage Driver"

第一种方式:指定容器启动默认磁盘大小

Overlay2驱动方式:不支持在线扩容

Docker容器默认启动的虚拟机,会占用宿主机的资源CPU、内存、硬盘),例如默认Docker基于Overlay2驱动方式,容器硬盘的rootfs 根分区空间是整个宿主机的空间大小。

可以指定默认容器的大小(在启动容器的时候指定),可以在docker配置文件:/etc/sysconfig/docker中,OPTIONS参数后面添加如下代码,指定Docker容器rootfs容量大小为10G:

vi /etc/sysconfig/docker

OPTIONS='--storage-opt overlay2.size=10G'

修改Docker存储配置文件,加入如下代码:(默认如果已经为overlay2,则无需修改)

vi /etc/sysconfig/docker-storage

DOCKER_STORAGE_OPTIONS="--storage-driver overlay2 "

然后重启docker即可;

 Overlay2 Docker磁盘驱动模式,如果要调整其大小,通过如上的方法,会导致Docker引擎服务无法启动,还需要文件系统设置为xfs,并且支持目录级别的磁盘配额功能;

CentOS7.x Xfs磁盘配额配置,新添加一块硬盘,设置磁盘配额方法步骤如下:

1)添加新的硬盘如图所示:

 2)格式化硬盘为xfs文件系统格式,命令如下:

mkfs.xfs -f /dev/sdb

3)创建data目录,后续将作为docker数据目录;

mkdir /data/ -p

4)挂载data目录,

mount -o uquota,prjquota /dev/sdb /data/

或者写入fstab执行mount -a

5)docker引擎默认数据存储目录:/var/lib/docker重命名,并且将/data/docker目录软链接至/var/lib/下即可;

mkdir -p /data/docker/

cd /var/lib/

mv docker docker.bak

ln -s /data/docker/  .

6)重启Docker服务,并且查看进程,可以看到docker overlay2.size大小配置,如图所示:

 7) 基于Docker客户端指令启动Docker容器,并且查看最新容器的磁盘空间为10G,则设置容器大小成功,如图所示:

以上方法只适用于新容器生成,并且修改后需要重启docker,无法做到动态给正在运行容器指定大小, 

3、Docker容器Disk硬盘资源扩容二(DeviceMapper驱动方式)

第一种方式:指定容器启动默认磁盘大小

DeviceMapper驱动方式:支持在线扩容

Docker容器硬盘热扩容操作记录centos 7里使用docker的时候默认存储引擎是Overlay2,而DeviceMapper驱动支持ext2、ext3、ext4,不支持xfs,而xfs是CentOS7的默认文件系统类型

所以建议docker服务器的文件系统格式调整为ext4(在centos7系统安装时可以手动指定所在分区为ext4格式)。

操作步骤:

1,以在docker配置文件:/etc/sysconfig/docker中,OPTIONS参数后面添加如下代码,指定Docker容器rootfs容量大小为10G:

OPTIONS='--storage-opt dm.basesize=10G'

 2,修改Docker存储配置文件,修改默认存储引擎为DeviceMapper,加入如下代码:(默认如果已经为devicemapper,则无需修改)

vi /etc/sysconfig/docker-storage

DOCKER_STORAGE_OPTIONS="--storage-driver devicemapper"

然后重启docker即可;

devicemapper Docker磁盘驱动模式,如果要调整其大小,通过如上的方法,会导致Docker引擎服务无法启动,还需要格式化文件系统设置为ext4,并且支持目录级别的磁盘配额功能;

CentOS7.x ext4磁盘配额配置,新添加一块硬盘,设置磁盘配额方法步骤如下:

 2)格式化硬盘为ext4文件系统格式,命令如下:

mkfs.ext4 -f /dev/sdb

3)创建data目录,后续将作为docker数据目录;

mkdir /data/ -p

4)挂载data目录下,vi /etc/fstab  && mount -a

5)将docker引擎默认数据存储目录:/var/lib/docker重命名,并且将/data/docker目录软链接至/var/lib/下即可;

mkdir -p /data/docker/

cd /var/lib/

mv docker docker.bak

ln -s /data/docker/  .

6)重启Docker服务,并且查看进程,可以看到docker dm.basesize大小配置,如图所示:

7) 基于Docker客户端指令启动Docker容器,并且查看最新容器的磁盘空间为10G,则设置容器大小成功,如图所示:

 

 

第二种方法:在线扩容正在运行容器指定大小 :

xfs文件系统修改文件系统大小命令:xfs_growfs

ext4文件系统修改文件系统大小命令:  resize2fs

1)查看现有的容器磁盘大小:

2)查看mapper设备:

3)查看卷信息表:

4)根据要扩展的大小,计算需要多少扇区:

第二个数字是设备的大小,表示有多少个512-bytes 的扇区. 这个值略高于 10GB 的大小。

我们来计算一下一个 15GB 的卷需要多少扇区,

echo $((15*1024*1024*1024/512))   31457280

5)修改卷信息表--激活--并且验证(红色3个部分)

echo 0 31457280 thin 253:2 62|dmsetup load docker-8:16-131100-7181dfff737acecb33c71d4b8dd79beef3bd84e34df6c4e51cd5096591548009

dmsetup resume docker-8:16-131100-7181dfff737acecb33c71d4b8dd79beef3bd84e34df6c4e51cd5096591548009

dmsetup table docker-8:16-131100-7181dfff737acecb33c71d4b8dd79beef3bd84e34df6c4e51cd5096591548009

6)修改文件系统大小:

先查看卷所在的目录是什么文件系统,centos7默认为xfs用xfs_growfs 命令,如果是ext4则用resize2fs命令

8)最后验证磁盘大小:

 

 

posted on 2019-09-19 15:14  走路带风的帅界扛把子  阅读(620)  评论(0编辑  收藏  举报