Docker容器技术实践

时间:2024-03-13 08:06:39
 

1.1 什么是docker

Docker是通过内核虚拟化技术(namespaces及cgroups、cpu、内存、磁盘io等)来提供容器的资源隔离与安全保障等。由于Docker通过操作系统层的虚拟化实现隔离,所以Docker容器在运行时,不需要类似虚拟机(VM)额外的操作系统开销,提高资源利用率。

 

1.2 docker自理解

相当于一个虚拟的应用打包器,但他属于一个进程,封装成一个镜像。

 

1.3 docker分为两大版本

docker ce、ee   社区版、企业版(收费)

 

1.4 Docker的主要目标是(构建,运输,处处运行)

构建:做一个docker镜像

运输:docker pull

运行:启动一个容器

每一个容器,他都有自己的文件系统rootfs

 

1.5 linux容器技术,容器虚拟化和kvm虚拟化的区别

1.5.1 kvm虚拟化

需要硬件CPU的支持,需要模拟硬件,可以使用不同的操作系统,启动时间分钟级

 

1.5.2 容器虚拟化

严格来说只是进程之间的隔离,不需要模拟硬件,共用宿主机的内核,启动时间秒级

 

1.6 docker容器虚拟化的好处

快速部署、轻松迁移、资源利用率高

 

1.7 Docker主要组件

镜像、容器、仓库

 

1.8 Docker是传统的C/S架构

分为docker client和docker server

 

使用命令:docker version       #可查看服务端与客户端,当服务端启动失败时,使用docker version会只看到客户端,会有报错。

 

1.9 docker环境准备

准备两台纯净的Centos7的虚拟机:

主机名

IP

配置

Oldboy-docker01

10.0.0.11

12g内存

Oldboy-docker02

10.0.0.12

12g内存

 

1.10 Docker的安装

wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo     #下载他的repo文件

 

sed -i 's#download.docker.com#mirrors.ustc.edu.cn/docker-ce#g' /etc/yum.repos.d/docker-ce.repo #因为上面下载的repo文件指向的是国外的docker官网源,国内网速下载国外会很慢,这里替换成中国科学技术大学的源地址去下载。

 

1.10.1 也可用yum安装

yum install docker-ce –y

rpm –qa|grep docker       #最后安装完后,看一下是否安装了。

 

实在不行就:yum install -y docker 直接点。

 

1.10.2 使用阿里云docker加速器下载(速度快、免费)

https://cr.console.aliyun.com/cn-beijing/mirrors

 

点击镜像加速器-CentOS-按照下面的提示把文件写入与重启docker服务

 

或执行以下操作:

mkdir -p /etc/docker

tee /etc/docker/daemon.json <<-'EOF'

{

  "registry-mirrors": ["https://r1ztx9gb.mirror.aliyuncs.com"]

}

EOF

systemctl daemon-reload

systemctl restart docker

 

1.11 Docker启动

systemctl start docker     #首先启动docker

 

1.12 启动第一个容器

docker run -p 80:80 nginx  #正在运行的时候,其实正在下载nginx最新版的镜,上面操作已经使用了阿里云的docker加速器,所以这边会很快下载完,前提不能被之前其他服务占用80端口,否则启动不了docker的nginx。 启动后,使用其他机器访问nginx,docker机器会出现日志,方便提示的作用。

 

1.13 docker镜像的常用管理命令

搜索镜像

docker search centos       #搜索镜像

 

返回结果说明:

镜像的名字 描述    点赞数 是否是官方的(有OK是官方的) 是否是自动构建的

 

说明:下载镜像的时候,优先选择点赞数比较多的。

 

下载镜像

docker search alpine           #搜索一个小文件下载测试

docker image pull alpine       #镜像内所有的操作都可用image后在tab查看,image也行,docker pull也性。

docker image ls                #查看已经下载了多少个镜像

 

查看镜像

docker images

 

删除镜像

docker rmi

 

导出镜像

docker save

 

例子:docker save alpine:latest >docker-alpine.tar.gz #alpine后面接上最新版本,导出的时候,把他另存为一个tar.gz的包

 

导入镜像

docker load

 

例子:docker image load –I docker-alpine.tar.gz      #导出后,再导入,-i是从哪里导入,也可以写路径。

 

注意:导入镜像也有一个import命令可以导入,但是用这个导入会导致镜像进不去/bin/bash或sh交互式模式,所以慎重!如果导入了,得重新使用load导入。

 

 

docker run nginx               #这种效果会一直在前台一直不断的耗着,跟没有加&一样

docker run –d nginx         #加了-d参数后就会在后台运行。

 

1.14 docker的容器管理

docker container inspect #说明书,详细的意思

Docker容器技术实践

说明:上面的是容器的ID地址,下面是容器的名字

 

 

docker container inspect 02dea79e52c7|grep -i ipaddr      #查看这个容器的IP地址。

curl 172.0.0.0.    #查看他显示出来的IP地址,然后直接curl打开一下,可以访问到主机,这就是容器通过html产生出来的网页,这时候只有本地能访问,外部不能访问,这就是没有在运行nginx的时候加上端口的原因。

 

docker run -d -p 80:80 nginx       #我们加上这个端口,相当于docker的端口映射

docker ps       #再去查看,会发现nginx最后面哪个80会指向一个80,这就是本地80映射给外部80端口的作用

docker –p端口映射的原理:其就在iptables上加了nat转换的规则,将80端口,转向了本地的80端口。

 

 

 

 

1.14.1 启动容器

docker run 容器名字  #启动docker不使用挂起其实是当场死掉,需配合-it交互式夯住来使用才能启动并挂起来使用这个镜像。

 

1.14.2 查看容器进程

docker ps –a      #-a是所有容器显示, 但使用ps命令搜索出来的容器名字是随机字符串,因为启动容器时没有直接指定名字。

 

例子:docker rm `docker ps -a -q`  #批量删除docker容器,docker ps –a –q参数是显示容器所有的ID,显示出来在配合docker删除命令删除。

 

1.14.3 停止容器

docker container stop 容器ID或容器名字

 

1.14.4 删除容器

docker container rm 容器的ID

 

1.14.5 进入容器

docker run –it nginx /bin/bash     #参数-i是交互式,参数-t终端,后面加/bin/bash原因是进入容器肯定要执行某些操作,所以要进入/bin/bash

 

说明:进入容器,相当于进入一个袋子系统类似,一个小型运行系统似的,进入这个小型系统里面大部分命令都没有,只有一些基础命令,比如unamr –r或者是查看版本这样。

 

docker exec –it 容器的ID或名字 在容器执行的命令

 

docker 容器只要后面不加命令,只要有返回结果就会秒退,所以要有个命令让他一直夯着,才能持续正常运行。

简单来讲:启动一个容器,一定要执行一个命令,不管什么命令,只要不输出结果让他一直夯住才能持续正常运行,否则秒退,这个容器的生命周期就没有了,相当于退出运行了。

 

1.15 杀掉容器进程

docker kill 容器的ID       #这种方式比较强制,因为他底层是一个进程,所以可以直接强制Kill掉。

 

1.16 让容器持续在后台运行的方法(docker容器的核心)

docker中的容器,如果想放在后台运行,需要第一个进程是处于一直夯住的状态,否则这个容器,就会处于退出状态!(简单来讲就是让它卡着那不动

 

一般不知道在容器里用什么命令,那就指定 /bin/bash进入一个交互模式,就不会回显效果,并且又能持续正常运行,最好的方式了。

 

1.17 进入Centos镜像的容器(说明进入容器参数的利端与弊端)

docker load 导入 进来centos镜像

docker run –it –name oldboy centos:latest /bin/bash     #启动一个容器,并且为这个容器起一个名字,还能指定版本,最后执行进入镜像的命令行模式。

ctrl+p 松开再ctrl+q        #这样退出容器,并且容器也还在运行,并不会完全退出,方便切出去处理其他不对的事情再切换回来这个容器继续操作。

docker attach oldboy   #刚才是临时退出,还想进去就输入这种命令也可以进入容器

nsenter     #这个命令来进入容器,会有些好处。

docker search centos6 #这样看效果不明显,所以pull下载一个Centos6和Centos7对比就会有明显效果。

 

docker exec –it oldboy /bin/bash      #这种进入容器的方式比较好

docker attach oldboy                   #这种方式进入容器的话,会有弊端。

docker inspect oldboy22|grep -i pid        #查看一个容器的PID,在使用nsenter穿越进去这个容器。

nsenter –t 21824 -m -u –i –n –p        #通过网络、像创建一个虚拟机一样,穿越进去,进去之后像bash类似,但是特点是没有终端,缺点是环境变量有些不一样,这种进入容器的方法比较难记忆,只要有个印象即好。

 

说明:第一种是exec单独的一个bash进程,不会造成同步操作,使用第二个进入容器的命令的话,就会同时使用一个bash进程,会造成同步,你exit退出了,另外一个attach的进程就会退出了。

 

 

1.18 Docker容器的网络访问(端口映射)

 

Docker网络原理图与说明

 Docker容器技术实践

 

说明:docker容器本身自带生产一个网卡,名为docker0,可在宿主机使用ip a查看,IP为172.17.0.1,每启动一个容器,容器会按照172.17.0.1下延伸设置容器的IP,所有容器会按照docker0这个网桥发送上外网请求给docker0网关地址172.17.0.1,网关地址通过本地设置的内核转发参数后出去,随后docker会自动设置iptables模拟转发规则,再交给宿主机网卡eth0,eth0网卡才与外网交互数据返回给docker容器,想要docker容器上网,必须前提设置内核转发,并确保宿主机能上网!

 

说明2:当虚拟机挂起时,容器此时还在运行,但ipv4内核转发的参数已经被切断,所以需重新一下docker容器,或更改ipv4的参数为1开启。 

 

 

docker run –d –p 0.0.0.0:80:80 nginx:latest      #运行一个nginx的容器,并且-d后台运行,并且-p指定映射,将本地的80端口映射到容器里的80端口

 

换端口再启动一个nginx实例:

docker run –d –p 0.0.0.0:81:80 nginx:latest      #将本机的81端口,映射到容器里的80端口,在外部打开需要指定10.0.0.7:81 而不是80了。

 

说明:此多端口开容器方法可开多个nginx容器,为了应对没有docker的情况下,负载均衡到了极限需要扩几台nginx机器要一大堆繁琐操作时,就可用这种方法快速启动部署多个nginx实例来帮忙抗住nginx并发压力,就不需初始化系统、编译nginx啥的。

 

可查看nginxdocker容器占用内存

free –m        #几乎占用的特别少,占用资源特别少,所以docker的好处就展现出来了。

 

指定多个端口

docker run –d –p 0.0.0.0:8080:80 –p 1122:22 nginx:latest       #加多个p参数就可以指定多个端口,1122端口的写法是本地宿主机的1122端口映射到容器的22端口,后面跟上容器与最新版本。

 

问题:这边指定这个容器里的某个端口指定物理机的某个端口,80端口有,但是22端口没有,这怎么回事呢?

 

解答:可进入这个容器的bash控制界面,这个nginx镜像的容器里的小型系统是Ubuntu系统的,所以在进入bash界面后要使用Ubantu的命令,例如apt-get install下载命令等去操作。

 

容器里启动sshd会报dbug的错误,解决办法:

说明:上方操作因指定了22端口,所以要用到22端口就必须容器里要有sshd的服务,使用Ubuntu系统的apt-get安装会出错,这里使用Centos的容器系统来操作。

 

docker run –it –p 2022:22 centos:latest /bin/bash       #前提必须要下载好Centos的镜像才能进入,这里启动进项并且本机的2022端口映射到容器里的22端口,并且进入一个bash控制终端。

 

yum install –y openssh-server     #安装ssh服务

systemctl start sshd   #启动ssh服务

 

报错信息:Failed to get D-Bus connection: Operation not permitted     #因为启动centos容器时Dbus-daemon没能启动,所以可去百度找答案,或者进入容器时指定Dbus来连接进去,就不会报错。(这个原因是因为dbus-daemon没能启动。其实systemctl并不是不可以使用,将你的cmd或者entrypoint设置为/usr/sbin/init即可。会自动将dbus等服务启动起来。

 

解决方法: docker run –privileged -d -p 2022:22 -e “container=docker” -v /sys/fs/cgroup:/sys/fs/cgroup centos /usr/sbin/init

 

docker -ps                             #找到刚才回显出来的容器ID

docker exec -it 容器的ID /bin/bash    #重新进入这个容器的bash控制台。

ps -ef      #查看进程,可看到容器启动时,启动的第一个进程是/usr/sbin/init,有了init引导就会启动dbus-daemon了,有了dbus就能启动systemctl。

yum install -y  net-tools       #因为Centos系统是纯净的,所以很多命令都不能用,这里安装一个命令工具包。

netstat -lntup                 #随后才能使用这个命令来查看容器里的端口22开启没。

ifconfig                       #这里使用ifconfig查看容器里的IP是多少。

echo 123456|passwd --stdin root    #给容器设置一个密码,否则没密码连接不上。

说明:以上操作都是容器里的Centos进行操作,没有指定映射端口前,宿主机可连接容器的IP进行连接,只有映射了端口后,才能在其他机器连接宿主机的IP并且指定好端口来连接。(一定要区分好,使用sshd的容器其实也就是套用sshd工具在宿主机里,不要搞混了。)

 

其他机器连接试一下:

ssh -P2202 [email protected]宿主机的IP         #能连接后使用密码就可以连接上,并且指定好本机映射的IP。

 

1.19 Docker的数据卷管理

例子:

docker run -d nginx:latest     #启动nginx这个容器

docker ps       #查看刚启动的容器的ID或名字

docker exec -it 容器的名字或ID /bin/bash       #进入容器里的bash控制终端

 

nginx的docker容器里操作:

ls  /usr/share/nginx/html      #一般猜测这个网上的容器的nginx目录会在镜像系统里的/usr/share/nginx/html

echo ‘hehe’>/usr/share/nginx/html/index.html     #将index.html主页的内容改为hehe,在外部宿主机可curl这个容器的IP地址查看内容是否更改。

 

宿主机操作:

docker inspect 容器的ID|grep -i ipaddr    #在宿主机外部使用docker命令的inspect过滤获取容器里的ip元数据。

curl nginx容器的IP    #可查看内容是否更改。

 

问题:此时想让容器里的nginx网站根目录使用的是宿主机外部的数据目录怎么操作呢?难道要传进去吗?下面会使用docker的挂载方法,将本机的目录数据挂载到容器里的某个目录,这样就能让容器能放我们的内容了。

 

数据卷(文件或目录)

-v /data        #这是我们宿主机存放web数据的目录位置,如果宿主机没有data目录,docker使用命令时会自动帮忙创建。

-v src:dst      #-v参数,src是外部宿主机的挂载位置地址,dst是docker镜像容器的挂载位置地址。

 

docker run -d --name nginx -p 80:80 -v /data:/usr/share/nginx/html nginx:latest        #启动nginx镜像容器,并且指定端口映射,将本机的80端口映射到容器里的80端口,并且挂载我本机的data目录到nginx容器里的/usr/share/nginx/html 目录。

 

echo ‘oldboy’ >index.html    #写一个主页文件测试。

 

在物理机浏览器访问:

http://10.0.0.7    #一访问宿主机的IP就能访问到容器里的80端口,里面挂载的目录内容也能成功访问。

 

说明:以后要更新内容,就直接在宿主机的/data目录就能这样更改,以后更新代码就方便好多。

 

数据卷容器(复制以挂载好目录的容器)

--volumes-from     #复制已指定好挂载源地址和目标地址的容器名字就可实现复制他的参数(相当于挂载跟他一模一样)

 

docker run -d --name nginx2 -p 81:80 --volume nginx:latest    #新开启一个nginx容器,命名为nginx2,指定端口不跟上面操作冲突,并且使用vlomue参数指定上一个nginx容器的挂载参数,使挂载参数一模一样。

 

说明:如果使用集群的话,这个参数会非常方便,只需启动nginx镜像容器时只需使用--volumes参数就能实现每台nginx的所有代码都更新在宿主机的一个目录里。

 

 

1.20 手动制作docker镜像

例子:

docker run -it -p 1122:22 guyton/centos6 /bin/bash    #将容器里的22端口映射到宿主机的1122端口,用的镜像是guyton/centos6,并且进入bash控制台。

cat /etc/redhat-release    #容器里查看系统版本信息,一看是Centos6.9的,一看就是小型的Centos6系统集成的镜像。

 

yum install -y openssh-server      #安装一个ssh服务

/etc/init.d/sshd start     #启动sshd服务,并且在/etc/ssh下生成dsa格式的公钥和私钥,rsa的公钥和私钥,这就是docker启动ssh服务时,ssh启动脚本在后台做的一些事情。

 

netstat -lntup     #检查22端口是否启动

 

让镜像就单启动ssh服务就夯住的方法:

/usr/sbin/sshd -D      #在进入Centos6的容器里的bash控制端在执行这个命令,启动ssh服务时,后面加上大写-D就能让他夯住,作用跟进入bash命令类似,单启动sshd夯住就行。

 

说明:我想让下次去到一个新地方时,那就可以将这些重复的yum下载与初始化做成一个镜像,我直接docker run启动这个ssh的镜像容器就能用,非常方便,不用那么多繁琐的操作。

 

制作镜像

docker commit keen_lichterman centos6-ssh      #复制刚才yum install好的初始化环境的容器,启动状态不保存,只保存文件在容器里,新建一个容器名字为centos6-ssh

 

docker images      #查看目前已有的镜像,看到有刚创建好的centos6-ssh的新镜像

docker run -p 2122::22 -d centos6-ssh /usr/sbin/sshd -D       #启动刚创建好的镜像,指定本地2122端口映射为容器里的22端口,并且让他指定第一个命令为/usr/sbin/sshd -D,第一个命令相当于第一个进程,他夯住了,就持续运行不会退出了。

 

docker -ps #查看刚启动的centos6-ssh镜像是否卡着/usr/sbin/ssh这个进程持续运行。

 

宿主机里操作:

ssh [email protected] -p 2122     #连接宿主机的2122端口,相当于连接容器里的22端口,输入密码也是输入容器里密码。

 

 

1.21 Docker启动容器时,既启动httpd又启动sshd(双服务)的方法

说明:以上操作,(启动docker对第一个进程夯住)都是对单个服务启动后给它夯住持续运行,但容器里有两个服务,让两个服务同时运行并夯住又是个问题,前面学了ssh的-D前台夯住的方法,但httpd夯住的方法还不知晓,所以这里就有一个另类实现方法,写一个脚本来并行执行,让ssh服务断后来夯住,这样就实现前面服务可不夯住,后面有人断后夯住的方法。

 

步骤一:先做好一个初始化镜像容器,将所有要下载和执行脚本的操作都做好,随后在克隆成新的,让后面人一次性启动。

docker run -it --name test centos6-ssh /bin/bash   #启动一个容器,容器名字待会在docker ps里叫test,容器是创建好ssh容器,里面有ssh服务,并且运行一个bash控制台。

 

rpm -qa|grep openssh   #检查之前yum的ssh在不在。

ps -ef      #检查进程运行状态,刚启动一个新的镜像容器时,他上一次正在执行的ssh等其他服务运行状态是不保持的,保持的容器里面的文件,例如服务的配置文件、网站根目录数据等。

 

yum install -y httpd   #下载一个apache,安装包比较小,可使用这个来测试。

vi  init.sh         #在根目录下创建一个脚本为init.sh,填上以下内容。

#!/bin/bash

/etc/init.d/httpd start    #启动httpd的命令填上去

/usr/sbin/sshd -D          #启动sshd并且夯住的命令在最后填写(注意一定要在最后,优先顺序特别重要!

 

chmod +x init.sh   #最后给init.sh脚本加上执行权限,否在docker那运行不起来,否则加 /bin/bash /init.sh来无x权限执行。

 

ctrl+p 松开 ctrl+q #临时退出一下,先让他暂时运行着。

 

 

步骤二:宿主机上操作,复制刚初始化的镜像容器,另存为一个新镜像容器名字

宿主机上操作:

docker ps         #查看刚才初始化好的并且正在后台运行的容器名字与ID

docker commit test centos6-httpd   #复制镜像,刚才运行的镜像容器在docker ps里是叫test的,所以指定test这个容器,并且另存为一个新的镜像名字。

docker images      #查看已有的镜像容器

docker run -d --name centos6-httpd -p 3022:22 -p 80:80 centos-httpd:latest /init.sh        #运行刚创建的centos6-httpd容器,因待会要测试用,所以端口映射,本机的3022端口指向容器的22端口,本机的80端口指向容器的80端口,使用镜像是使用本仓库默认的版本,并且容器第一个执行的进程是/init.sh,他会并行执行最后夯住,一定要加/斜号,告诉他脚本位置并执行。

 

docker ps       #查看刚启动的镜像的ID或名字,看到已经启动,并且用init.d脚本挂载夯住正常运行了。

 

步骤三:使用物理机访问刚制作好的新镜像。

物理机访问浏览器测试:

http://10.0.0.7

ssh [email protected] -p 3022  #连接后,可使用ps -ef查看进入容器里面的进程,可以看到先启动的是init这个脚本,后面是apache默认参数启动的多个work线程,这种情况输入正常情况,因apache还没改配置文件,所以默认启动多个work进程,最后ssh连接也有一个ssh进程,最后有一个ssh来夯住。

 

 

1.22 dockerfile自动构建docker镜像(创建一个镜像)

 

重要说明:需要提前准备好rootfs.tar.xz文件,否则无法完成以下操作,docker的常用的子系统rootfs。

 

rootfs下载地址:https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/ubuntu/trusty/amd64/default/20180824_07%3A43/

 

说明:这个网址是从学习视频里发现的,比较好运,否则还找不到,如报错404找不到,那就到https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/ubuntu/trusty/amd64/default/ 下去找最新版本的目录进去找rootfs.tar.xz下载。

 

 

dockerfile主要组成部分:

    基础镜像信息

    维护者信息

    镜像操作指令

    容器启动时执行指令

 

dockerfile常用指令:

    FROM 这个镜像的妈妈是谁?(指定基础镜像)

    MAINTAINER 告诉别人,谁负责养它?

    RUN 你想让它干啥(在命令前面加上RUN即可)

    ADD 给它点创业资金(COPY文件,会自动解压)

    WORKDIR 我是cd,今天刚化了妆(设置当前工作目录)

VOLUME  

EXPOSE  (对外暴露的端口,一般配合-P 启动容器随机端口使用,后查看容器随机端口对应的是哪个端口,来给用户连接)

CMD 容器启动时候默认执行的命令

 

操作步骤:

环境硬性准备工作:

cd /opt/

mkdir centos6-base

cd centos6-base/       #rootfs.tar.xz文件放到目录下,后面需要解压并且生成一个小型的系统,rootfs.tar.xz是docker的前身系统,前提得准备好rootfs.tar.xz文件才能做,是根据lcx系统文件里面的rootfs.tar.xz文件做的,需要找到他,否则做不了。

 

填写硬性配置文件:

vim Dockerfile     #新建一个Dockerfile文件,官方格式名字就叫这个,最好不要更改,保持规范就好,一定要在centos6-base目录下新建。

FROM scratch       #做最基础镜像时,最好填写scratch白手起家的意思,从谁的基础上开始做这个小型系统,类似导入一个镜像,从这个镜像继续操作,如果没有镜像,那不以任何镜像为基础,写法就为:FROM scratch,同时说明接下来所写的指令将作为镜像的第一层开始,相当于它是在自己作镜像。

ADD rootfs.tar.xz /    #添加一个文件,ADD这个功能能自动解压这个文件,并且能制定解压后的位置,在镜像的/根目录下。

CMD [“/bin/bash”]      #容器启动时,默认执行的命令,启动/bin/bash

 

开始制作镜像:

docker image build -t centos6-base .    #使用build -t命令指定制作完后的镜像名字为centos6-base,并且指定Dockerfile文件的位置,那个点.是在当前目录下,因为刚进入了centos6-base目录下,所以文件也在那,命令在当前目录下执行的,也可写文件绝对路径。

 

docker images   #查看制作好的镜像,并且找到centos6-bash的镜像名字。

 

进入制作好的镜像:

docker -run -it --name oldboy-base centos6-base:latest    #dockerfile制作镜像前在cmd指定了默认启动后执行的命令在/bin/bash,否则没有指定cmd就会报错启动不了。

 

说明:以上操作都只是做一个最最基础的bash镜像,相当于用centos或Ubuntu的底层系统来做的一个小系统。

 

镜像后加latest的原因:加了latest是使用当前仓库默认的办法,也可以指定最新的版本,也有一些小区别,相当于使用当前版本还是使用最新版本的区别。

 

 

使用dockerfile制作应用场景服务的镜像,不在是基础系统镜像,而是有服务的镜像:

说明:当给人家一个镜像的时候可能要1个G,但让他使用我的dockerfile文件制作镜像时,会非常快,并且传输非常方便,不用发上G的文件,最小几十M。

 

操作步骤:

环境硬性准备工作:

mkdir centos6-ssh

cd /otp/centos6-ssh

 

容器的启动脚本配置文件:

vim init.sh        #在/opt/centos6-ssh目录里编写启动脚本。

#!/bin/bash

echo 123456|passwd --stdin root    #因镜像容器要开启ssh服务,如果容器里没有密码,有ssh也连接不上,这里给机器赋予一个密码。

/etc/init.d/httpd start        #启动好httpd服务

/etc/init.d/sshd start         #重点:要启动一次sshd后会生成公钥私钥对,否则不启动一次来生成,会启动容器时会报错。

tail -f /var/log/httpd/access_log  #重点:可不使用/usr/sbin/sshd -D来夯住,可使用tail 命令持续查看httpd的日志,前提知道日志路径,不要瞎猜。

 

填写硬性配置文件:

vim dockerfile

FROM scratch           #白手起家,表示自己个人制作基础镜像文件。

ADD rootfs.tar.xz /    #添加一个文件,将根目录下的rootfs.tar.xz文件解压到容器里的/根目录下

RUN yum install openssh-server httpd -y            #在构建镜像时要执行的命令,相当于还未执行镜像前要做的初始化操作的命令。

ADD init.sh /init.sh    #添加一个文件,将dockerfile目录下的init.sh启动脚本,拷贝到容器里的/根目录下,里面写好了要操作什么和夯住的命令。

CMD ["/bin/bash","/init.sh"]       #启动镜像时默认执行的命令,执行/bin/bash并且拼接再执行容器里的/init.sh脚本,帮助启动服务和初始化服务。

 

开始制作镜像:

docker build -t centos-ssh-httpd . #build -t制作一个镜像,新制作的镜像名字为centos-ssh-httpd,这个点并且指定dockerfile文件的位置,可写全路径。

重点:因上面操作已经制作过一次FROM scratch等操作了,这就会做为docker的一个缓存,重新制作镜像时,做过的操作会快速执行,没做过的就会等一会。

 

重点2:刚到工作生产环境中,制作镜像名字一定要docker images查看已有的镜像名字,否则重复之前镜像名字会顶替掉原来的,并且原来的镜像名字会出现为空,这样会不知道哪个镜像是哪个镜像,就乱套了。

 

 

进入制作好的容器:

docker run -d -p 80:80 -p 1022:22 centos-ssh-httpd    #运行刚制作好的容器,指定映射端口,本地的80端口指向容器的80端口,本地的1022端口指向容器的22端口,后面如果指定了运行容器要执行的命令就会替换掉dockerfile构建时cmd的命令,之前的服务都没启动,这是重点。

 

测试服务是否正常:

http://10.0.0.7           

ssh [email protected] -p1022

 

说明:填写dockerfile文件时,ADD就像开头,CMD相当于结尾,他们中间写的就是构建的命令,比如ADD添加完了文件,然后写一些其他操作,写入文件修改文件等的命令,到了CMD相当于后面要执行的操作,执行脚本等,类似于ansible写playbook剧本类似原理。

 

 

 1.23 docker引用传参方式指定每次登陆容器的登陆密码

说明:当使用dockerfile创建一个镜像时,他的密码一般都被指定为一个固定的密码,例如echo 123|passwd --stdin root 这样的方式,每当使用镜像时都输入这个统一的密码,当公司有人要离职后,如果密码不更改,离职的员工泄露读独自登陆docker容器的ssh做事情,那就非常麻烦,数据不安全,所以要使用init.sh起始脚本设置初始化密码要使用变量方式来传参,(达到每次使用容器就指定不同的密码)让容器、数据变安全!

 

步骤一:找到容器第一个启动脚本,指定每次的登陆密码由管理人员随时传参控制

vim init.sh       

#!/bin/bash

echo $ssh_pwd|passwd --stdin root      #bash脚本里指定一个$ssh_pwd变量,设置这个是容器系统里的一个全局变量,让用户在外指定变量值是多少传递进来。

/etc/init.d/httpd start       

/etc/init.d/sshd start        

tail -f /var/log/httpd/access_log

 

步骤二:启动docker时指定docker容器系统里的密码,让用户连接时每次都能设置不同的密码。

docker run -d -p 82:80 -p 5022:22 -e “ssh_pass=12345678” centos-ssh-plus        #启动docker时使用-e参数指定好ssh_pass变量的值为12345678,然后在启动init.sh的脚本,值就有了。

 

说明:使用ssh连接方式登陆到这个容器里去查看刚才登陆容器赋值ssh_pwd的值是看不到环境变量有ssh_pwd的,必须得登陆到docker原来容器的bash环境下才能查看的到环境变量。

 

应用场景

类似于实验楼,给你虚拟化一个环境来做实验,基本就是一个docker容器里的一个小型linux系统,开一个实验页面相当于一个显示出随机密码的docker信息发到页面给用户登陆,并且会定时会清理docker容器,只有充钱才能变让docker系统变得持久。

 

应用场景2  

类似于实验楼,能做更多IP与主机信息与业务nginx上,做一个变量设置,这样就能用户用我们的docker,就能告知用户指定什么变量是修改什么,或修改业务中自己的信息,从而实现更多制定化docker,快速准备业务。

 

个人理解dockerfile

dockerfile文件只收集类似shell 过程改变的记录,给人家执行这些操作来自动下载自动改变,和设置我们指定的参数,就需启动按照我们给用户的说明来设置启动。

 

 

dockerfile可道云小项目实验

说明:每一个项目最好为一个文件夹,例如nginx,就在/opt/dockerfile/nginx目录下新建dockerfile文件来编排构建

说明2:此处我使用的是本地源为下载源,源地址主要区分好系统是6或7,可去清华园,163源去替换以下源地址。

 

1、编写dockerfile
FROM centos:6.9
RUN echo '192.168.16.77 mirrors.aliyun.com' >>/etc/hosts && \
rm -fr /etc/yum.repos.d/CentOS-Base.repo && \
curl http://192.168.16.77/repo/Centos-6.repo -o /etc/yum.repos.d/CentOS-Base.repo && \
yum makecache && \
yum install php php-cli -y && \
/etc/init.d/httpd start && \
cd /var/www/html/ && \
curl http://192.168.16.77/kodexplorer4.33.zip -o kodexplorer4.33.zip && \
yum install unzip -y && \
unzip kodexplorer4.33.zip && \
chmod -R 777 /var/www/html/ && \
yum install php-gd php-mbstring -y && \
/etc/init.d/httpd restart && \
yum install -y openssh-server
ADD init.sh /init.sh
CMD ["/bin/bash","/init.sh"]

 

 2、项目目录下脚本,名为init.sh

 
#!/bin/bash
/etc/init.d/httpd start
/etc/init.d/sshd start
echo "123456"|passwd --stdin root
tail -f /var/log/httpd/access_log
 

 

 3、开始构建制作docker镜像

 docker image build -t centos_testv2 .#制作后的镜像名为centos_testv2,dockerfile文件在本目录,所以填写.

 

4、启动刚制作的docker镜像,并指定映射端口

docker run -d -p 8080:80 -p 8022:22 centos_testv2 #-p指定两个httpd与ssh端口映射。

 

5、查看最后一个启动的容器是否夯住启动成功

docker ps -l 

 

6、用户访问宿主机IP的效果图

 Docker容器技术实践

 

 

docker常用项目镜像下载地址

http://docs.docker.com/samples/library/

 

 

1.24 docker镜像的分层(dockerfile构建快慢,缓存原理)

说明:镜像的分层类似于虚拟机的链接克隆,当你有一个模板镜像时,你在去克隆一个docker容器,会非常快,是因为他已经有存储的文件,99%每个系统文件都一样,只有一小部分是改变层,所以比较快,不像VM虚拟机的完整克隆一样完整克隆过来非常慢。

 

1.24.1 docker镜像分层原理图

 Docker容器技术实践

说明:每克隆一个镜像,他的系统最底层base rootfs是不会变的,因为以这个为基础,这是第一层,第二层于dockerfile里的第二步改变了什么,加了什么,如果没有改变,就很快的克隆,如果有改变,当克隆第二个镜像时,他会从模板的改变层(改变1)后面延伸给第二个镜像继续往下重新构建一个镜像系统,这样就会时间有点长,相当于克隆镜像的原理,他们变化的流程,快速复制的原理。

 

小总结:没改变的层就继续复制,改变的层就会从那一层从外延伸新的层,后面所有层就重新构建了,相当于重新构建而不是复制已有的了,因为他的改变层不是跟之前模板是有关系的了,相当于父亲变了,就重新延伸发展了,每一层都相当有固定ID的,他的ID就是他的sha256,当改变层跟之前模板的sha256的ID不同了,就相当于找不到他爹了,找不到他父亲了,所以就会重新延伸发展新的,就相当于重新来花时间构建了。

 

说明2:这就是为什么dockerfile加了一行就重新构建这么慢了,人家构建怎么这么快呢的原因,懂了这个原理,以后再构建镜像时只要想快速构建,就要尽可能的改最往后的一行,到最后一步改变了构建也会很快。

 

 

1.25 docker多个容器进行网络连通(zabbixmysqlweb

docker的理念来推荐一个容器只运行一个服务,不然一个容器死了,整个架构就死了,但一个服务里有很多个组件配合起来才能成为一个架构体系,所以就要让每个docker容器进行连通通信来交互成为一个架构。

 

zabbix官方使用参数配合连通的例子:

https://www.zabbix.com/documentation/3.2/manual/installation/containers       #有代码说明,直接复制即可。

 

 

步骤一:将所有包装应用服务的镜像导入到宿主机里,这里举例将zabbix所有组合套件拉进来(zabbix官网下载镜像)

docker pull mysql/mysql-server #未指定版本,默认pull下载最新版本。

docker pull zabbix/zabbix-server-mysql

docker pull zabbix/zabbix-web-nginx-mysql

docker pull zabbix/zabbix-java-gateway

 

说明:有个小规律,是zabbix里的镜像,就必须在包的前面加上zabbix,是mysql的包就前面加上mysql

 

 

步骤二:将刚才下载好的镜像进行指定参数来启动,(并指定环境变量参数做好连通

mysql镜像启动

# docker run --name mysql-server -t \

      -e MYSQL_DATABASE="zabbix" \                    #每个都是变量,设置变量值等于谁,然后其他脚本都是已经设置好变量来接收了。

      -e MYSQL_USER="zabbix" \

      -e MYSQL_PASSWORD="zabbix_pwd" \

      -e MYSQL_ROOT_PASSWORD="root_pwd" \

      -d mysql:5.7 \                                              #此处指定mysql5.7版本,因上面pull的mysql未指定版本,所以pull时自动装最新版本,跟这不匹配,所以重新下载5.7版本。

      --character-set-server=utf8 --collation-server=utf8_bin         #最后指定字符集

 

java-gateway镜像启动

# docker run --name zabbix-java-gateway -t \

      -d zabbix/zabbix-java-gateway:latest

 

zabbix-server-mysql镜像启动

# docker run --name zabbix-server-mysql -t \

      -e DB_SERVER_HOST="mysql-server" \

      -e MYSQL_DATABASE="zabbix" \

      -e MYSQL_USER="zabbix" \

      -e MYSQL_PASSWORD="zabbix_pwd" \

      -e MYSQL_ROOT_PASSWORD="root_pwd" \

      -e ZBX_JAVAGATEWAY="zabbix-java-gateway" \

      --link mysql-server:mysql \

      --link zabbix-java-gateway:zabbix-java-gateway \

      -p 10051:10051 \

      -d zabbix/zabbix-server-mysql:latest

 

zabbix-web-nginx-mysql镜像启动

# docker run --name zabbix-web-nginx-mysql -t \

      -e DB_SERVER_HOST="mysql-server" \

      -e MYSQL_DATABASE="zabbix" \

      -e MYSQL_USER="zabbix" \

      -e MYSQL_PASSWORD="zabbix_pwd" \

      -e MYSQL_ROOT_PASSWORD="root_pwd" \

      --link mysql-server:mysql \

      --link zabbix-server-mysql:zabbix-server \

      -p 80:80 \

      -d zabbix/zabbix-web-nginx-mysql:latest

 

说明:以上所有操作最好关闭其他占用80端口,3306端口否则启动不了docker里面指定的端口,会报错,提示占用。

 

 

步骤三:zabbix客户端机器安装zabbix-agent进行与zabbix服务端进行连接接受控制。

https://mirrors.tuna.tsinghua.edu.cn/zabbix/zabbix/3.2/rhel/7/x86_64/         #按照zabbix的版本下载客户端agent的版本,配置文件填写zabbix服务端的宿主机IP。

 

 

1.26 docker搭建私有仓库

说明:搭建非常简单,只需要下载registry镜像再启动就可以。

 

docker pull registry       #下载registry镜像

 

docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry         #当docker服务重启时,这个镜像会自动重启,这是--restart=always参数的作用,并且-v将本地的/opt/myregistry的目录挂载到容器里的/var/lib/registry目录。

 

docker ps       #可找到registry这个容器已经启动了。

docker image tag docker.io/centos6-base 10.0.0.7:5000/oldboy/centos6-base     #给现有的Centos6-base镜像定义一个标签,指定现有镜像,镜像都在docker.iot目录,最后指定tag标签的名字,此处加上仓库地址比较好记忆,如果没有就加上其他镜像。

 

docker images   #此时可看到创建好的镜像标签id与现有的centos6-base的id一模一样,相当于使用同一个镜像而已。

 

docker push 10.0.0.7:5000/oldboy/centos6-base      #这里使用push推送到docker的默认仓库目录里,此处会报错一个错误,版本更新过后只能使用https,这可以解决。

 

解决仓库https方法:

vim /etc/docker/daemon.json        #编辑docker的某个配置文件

 

{

  "registry-mirrors": ["https://r1ztx9gb.mirror.aliyuncs.com"],           #注意后面有个逗号,json的配置文件的格式都是这样,加一行内容。

  "insecure-registries": ["10.0.0.7:5000"]      #写上这个内容注意中文字符,逗号符号问题,写上docker的仓库地址,使其推送这个地址时,使用http方式推。

}

 

重点说明:文件不能有多余空格,也不能多一行,否则出错,可使用cat -A 查看。

 

 

systemctl restart docker       #重启docker服务

docker ps   #查看registry服务是否正常运行状态,并且端口没有占用5000端口,因为加了参数所以重启docker服务会自动重启registry容器

docker push 10.0.0.7:5000/oldboy/alpine        #重新push这个alpine的镜像应该就可以了。

 

在其他docker机器上要使用内网私有仓库的操作步骤: 需要使用私有仓库地址的机器上操作

vim /etc/docker/daemon.json        #编辑使用仓库的客户端的daemon配置文件,写入以下内容,内容作用是下载加速

 

{

  "registry-mirrors": ["https://r1ztx9gb.mirror.aliyuncs.com"],  

  "insecure-registries":["10.0.0.7:5000"]

}

 

systemctl restart docker       #重启docker生效。

docker pull 10.0.0.7:5000/oldboy/alpine        #下载docker服务端仓库里的alpine应该就成功了。

docker images      #可查看现有的镜像,已经有了刚下载的alpine

 

curl http://10.0.0.7:5000/v2/_catalog      #通过curl命令查看docker仓库里是否已经添加成功了镜像在里面的方法。

{"repositories":["oldboy/alpine"]}     #这里已经有了,这是完整的镜像路径地址。

 

 

1.26.1 docker搭建私有仓库的密码认证

说明:当私有仓库的地址被外面的人知道后,可以随意下载你的容器镜像,并且可以看到容器里面的资料然后泄露资料,并且可以上传一大堆后门的镜像来反弹nc做一些其他后门就非常危险,所以要给仓库锁上一个认证,谁要用我的仓库就必须要给密码,才能进行下载和上传。

 

mkdir /opt/registry-var/auth/ -p

 

yum install httpd-tools.x86_64 -y

htpasswd -Bbn oldboy 123456 >>/opt/registry-var/auth/htpasswd #添加一个认证用户和密码,生成为一个仓库里的一个认证文件暂时放着,密码是密文加密的。

 

docker run -d -p 5000:5000 -v /opt/registry-var/auth/:/auth/ -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry       #挂载刚才生成的认证文件到容器里的/auth里,然后设置一些环境变量。

 

记得把冲突解决,有端口冲突。       #不知是否要kill掉5000正在启动的容器,在重新启动容器,因为修改了5000容器的文件。

 

 

 

 

1.27 docker个人理解总结

docker与k8s或kvm一样的原理,都相当于命令行、进程式的虚拟机而已,docker特点都是快,占用内存比较小一些,命令行操作挂载等技术,非常方便又兼容强大。

 

 

1.27.1 Docker故障报错

故障一:

[[email protected] docker]# docker run -p 80:80 NGINX

/usr/bin/docker-current: Error parsing reference: "NGINX" is not a valid repository/tag: repository name must be lowercase.

See '/usr/bin/docker-current run --help'.

 

说明:这是没有启动nginx所造成的。

 

故障二:

 Docker容器技术实践

 

说明:因为没有在国内找到最新版本的docker镜像,所以就默认去国外去找docker镜像了,但是国内网去国外下载就下载不了,这里显示超时了,

这里推荐国外加速器来进行下载:阿里云加速器,daocloud加速器,中科大加速器。

 

1.28 Docker常用命令思维导图总结

Docker容器技术实践

 

转载于:https://www.cnblogs.com/shell520/articles/9758594.html