Docker
容器技术已经成为应用程序封装和交付的核心技术
容器技术的核心有以下几个内核技术组成:
Cgroups(control groups) 资源管理
namespace 进程隔离
selinux 安全
docker是完整的一套容器管理系统, 提供了一组命令, 让用户更加方便直接的使用容器技术, 而不需要过多关心底层内核技术
docker的优点:
相比与传统的虚拟化技术, 更加简介高效
传统虚拟机需要给每个VM安装操作系统, docker不需要
容器使用的共享公共库和程序
docker的缺点:
容器的隔离性没有虚拟化强
公用linux内核, 安全性有先天缺陷
selinux难以驾驭
监控容器和容器排错是挑战
镜像:
在docker中容器是基于镜像启动的
镜像是启动容器的核心
镜像采用分层设计
使用快照的COW技术, 确保底层数据不丢失

部署Docker
- 需要64位操作系统,必须7以上的版本,而且要卸载防火墙。
- 配置yum源,docker的软件包位于光盘RHEL7-extras.iso CentOS-7.5-1804.iso
- mount -t iso9660 -o ro,loop CentOS-7.5-1804.iso /var/ftp/centos-1804
- mount -t iso9660 -o ro,loop RHEL7-extras.iso /var/ftp/extras
- yum remove firewalld-* //卸载防火墙
- yum -y install docker
- systemctl start docker //启动docker
- systemctl enable docker
相关命令:
docker images //查看已有的镜像
docker search busybox //要求虚拟机可以上网,下载镜像。 带ok字样的是官方的
docker pull docker.io/busybox //下载镜像
docker push docker.io/busybox //上传镜像
docker images //再次查看
文件名REPOSITORY 标签TAG 编号ID IMAGE ID CREATED SIZE
docker.io/busybox latest 83aa35aa1c79 7 days ago 1.22 MB
镜像的备份与恢复:
- 镜像如果不写 标签默认就是latest
镜像名称(文件名) + 标签 == 唯一!
docker save docker.io/busybox:latest -o busybox.tar -o 输出为文件 文件名任意 //镜像打包
scp busybox.tar root@192.168.1.22:/root
docker load -i busybox.tar -i为input为导入 可以docker load --help查看 //镜像导入
容器的镜像采用分层设计最大255层,下面的层都是只读的
docker history docker.io/busybox:latest //查看镜像历史 了解镜像制作过程
docker inspect docker.io/busybix:latest //查看镜像底层信息
docker tag //创建链接,复制
docker rmi //删除本地镜像
镜像里面可以是服务和系统,服务和系统是一种应用
六个命名空间:
- 隔离主机名
- 隔离文件系统 在容器里创建文件,源主机看不见
- 隔离用户
- 隔离网络 ip地址不同但是可以ping通
- 隔离进程 进程的pid是跟真机不同
- 信号相量
启动容器相关命令:
docker run -参数 镜像名称:标签 启动命令
- 交互参数 -i
- 终端参数 -t
- 后台参数(服务) -d
[root@kubenode-01 ~]# docker run -it docker.io/centos:latest /bin/bash
#这样就进入到容器里了
[root@5bf2300e4a43 /]# hostname
5bf2300e4a43
隔离用户
[root@kubenode-01 ~]# cat /etc/passwd | wc -l
43
[root@5bf2300e4a43 /]# cat /etc/passwd | wc -l
15
隔离网络
[root@kubenode-01 ~]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.21 netmask 255.255.255.0 broadcast 192.168.1.255
[root@5bf2300e4a43 /]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 0.0.0.0
隔离文件系统
[root@5bf2300e4a43 /]# mkdir test ; ls /
bin dev etc home lib lib64 media mnt opt proc
root run sbin srv sys test tmp usr var
[root@kubenode-01 ~]# ls /
bin dev file lib media opt root sbin sys usr
boot etc home lib64 mnt proc run srv tmp var
kubenode1上并没有刚才创建的test目录
隔离进程
[root@5bf2300e4a43 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 10:16 ? 00:00:00 /bin/bash
root 79 1 0 10:27 ? 00:00:00 ps -ef
#一个系统不可能有两个PID一样的进程
[root@kubenode-01 ~]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 17:13 ? 00:00:03 /usr/lib/systemd/systemd --switched-root --system --des
root 2 0 0 17:13 ? 00:00:00 [kthreadd]
启动nginx镜像创建容器
[root@kubenode-01 ~]# docker run -itd docker.io/nginx:latest
fd43bf1bf45e6777fa9b0b08d24d2a316cda8fd5f0b7f74f2588025f469e9f26
[root@kubenode-01 ~]# docker ps 查看启动的容器
CONTAINER ID
fd43bf1bf45e (容器ID)
[root@kubenode-01 ~]# docker inspect fd 查看容器的相关信息,得知IP地址
.....
"IPAddress": "172.17.0.2",
.....
[root@kubenode-01 ~]# curl http://172.17.0.2
<!DOCTYPE html>
....
<title>Welcome to nginx!</title> #启动成功
......
docker ps 查看正在运行的容器 加 -a 是查看所有容器
docker ps -aq 查询所有运行容器的id
docker stop //关闭容器
docker run -itd docker.io/nginx:latest //加-d选项在后台运行
docker inspect 容器id //查询容器的详细信息
docker start 容器id //开启容器
docker stop 容器id
docker restart //重启容器
docker top 容器id //查看容器中的进程
docker rm 容器id //删除容器,删除启动中的容器时要加-f选项
docker rm $(docker ps -q) //删除括号命令中的执行结果
docker exec -it 容器id /bin/bash //进入容器。
echo $$ //显示当前的pid号
docker attch 容器id //以上帝身份进入容器(一般排错用,尽量不用)
如果pid是1 exit容器回被关闭!
自定义镜像
- 先进入一个容器
- 可以在容器里下载软件包等操作。。
- 退出容器
- 执行docker commit 容器ID 镜像名称:标签名称
dockerfile关键词:
- FROM:基础镜像
- ADD:复制文件到镜像 宿主机的文件放到容器里去
- RUN:在容器内执行命令
- CMD :容器启动时执行的命令
- ENV:设置变量
- EXPOSE:开放的端口
- WORLDIR :定义容器默认工作目录,作用相当于cd
- CMD的语法格式
/bin/ls -l -a
CMD [ “/bin/ls”, “-l”,"-a"]
书写dockerfile:
[root@kubenode-01] # mkdir demo ; touch local.repo dockerfile
[root@kubenode-01 demo]# ls
dockerfile local.repo
#local.repo 必须在跟 Dockerfile文件的相同目录中
[root@kubenode-01 demo]# vim dockerfile
FROM docker.io/centos:latest //基于centos:latest 镜像做
RUN rm -rf /etc/yum.repos.d/*.repo //RUN表示在容器内执行命令
ADD local.repo /etc/yum.repo.d/local.repo //将真机的local.repo文件拷贝到容器里
#local.repo 必须在跟 Dockerfile文件的相同目录中
RUN yum -y install net-tools bash-completion iproute vim psmisc
[root@kubenode-01 demo]# docker build -t new.io:test . #必须在dockerfile所在目录下操作
Sending build context to Docker daemon 3.584 kB
Step 1 : FROM docker.io/centos:latest
---> 76d6bc25b8a5
Step 2 : RUN rm -rf /etc/yum.repos.d/*.repo
---> Running in afd64221b997
---> 02c37cc3f241
.......
[root@kubenode-01 demo]# docker images
REPOSITORY TAG IMAGE ID CREATED
new.io test f1b594b99f70 7 minutes ago
书写dockerfile自定义web网站
先启动一个容器测试:
[root@kubenode-01 web]# docker run -it my.io:test
[root@e0edacd90733 /]# yum -y install httpd
[root@e0edacd90733 /]# systemctl restart httpd #报错,容器里自己是没无法启动服务
[root@e0edacd90733 /]# rpm -ql httpd | grep service
/usr/lib/systemd/system/htcacheclean.service
/usr/lib/systemd/system/httpd.service
[root@e0edacd90733 /]# cat /usr/lib/systemd/system/httpd.service
[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/httpd #运行环境
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND #启动命令
…
[root@e0edacd90733 /]# cat /etc/sysconfig/httpd #查看运行环境需要的变量
[root@e0edacd90733 /]# exit #退出容器
[root@kubenode-01 ~ ]# mkdir web
[root@kubenode-01 web]# touch dockerfile
[root@kubenode-01 web]# vim dockerfile
FROM my.io:test
RUN yum -y install httpd
ENV LANG=C
WORKDIR /var/www/html
EXPOSE 80
CMD ["/usr/sbin/httpd"," -DFOREGROUND"]
RUN echo ‘Hello world’ > /var/www/html/index.html
:wq
[root@kubenode-01 web]# docker build -t myweb.io:httpd .
[root@kubenode-01 web]# docker images
REPOSITORY TAG IMAGE ID CREATED
myweb.io httpd 8696c3f5e63d 20 seconds ago
[root@kubenode-01 web]# docker run -itd myweb.io:httpd
cb73c033eff96867b22537e3fd14df1dd740822cbc34ac0ba3897c0a98e1a25e
[root@kubenode-01 web]# docker inspect cb
[root@kubenode-01 web]# curl http://172.17.0.3
Hello world
自定义私有仓库
1.安装软件包并启动私有仓库
[root@kubenode-01 ~]# yum -y install docker-distribution.x86_64
[root@kubenode-01 ~]# systemctl start docker-distribution.service
[root@kubenode-01 ~]# systemctl enable docker-distribution.service
[root@kubenode-01 ~]# ss -ntulp | grep 5000
tcp LISTEN 0 128 :::5000 ::😗 users:
[root@kubenode-01 ~]# curl http://192.168.1.100:5000/v2/_catalog //访问私有仓库
{“repositories”:[]}
2.宣告docker的仓库地址(修改所有docker主机的配置文件)
- 停止所有容器
[root@kubenode-01 ~]# vim /etc/sysconfig/docker //修改主配置文件
修改13,23行
INSECURE_REGISTRY=’–insecure-registry 192.168.1.100:5000’ //允许非加密方式访问仓库
ADD_REGISTRY=’–add-registry 192.168.1.100:5000’ //docker仓库地址
:wq
[root@kubenode-01 ~]# systemctl restart docker
curl http://192.168.1.100:5000/v2/_catalog //访问测试
[root@kubenode-01 ~]# rsync -av /etc/sysconfig/docker root@192.168.1.22:/etc/sysconfig/docker
[root@kubenode-02 ~]# systemctl restart docker
curl http://192.168.1.100:5000/v2/_catalog //访问测试
3.上传镜像到私有仓库(必须打标签)
docker tag myos:httptest 192.168.1.100:5000/myos:httptest //打标签
docker push 192.168.1.100:5000/myos:httptest //上传镜像
curl http://192.168.1.100:5000/v2/_catalog
curl http://192.168.1.100:5000/v2/myos/tags/list //查看标签
4. 使用镜像启动容器
docker02利用仓库中的镜像启动容器
docker run -it 192.168.1.100:5000/myos:latest //下载镜像生成容器
/var/lib/registry/ //存放镜像的目录,要删除镜像进入目录里
持久化存储
卷的概念:
-
docker容器不保持任何数据
-
重要数据请使用外部卷存储
-
容器可以挂在真实机目录或共享存储为卷
docker run -it -v 宿主机目录或文件:容器内目录或文件 myos:latest
映射目录
修改主机的映射目录就是修改容器里被映射的目录
[真机: ] #docker run -itd -v /tmp:/httpd myos.httpd 将宿主机的tmp目录映射到容器里叫httpd
[真机: ] #docker exec -it 00 /bin/bash
[容器 00:] # cp /etc/httpd/conf/httpd.conf /httpd
[容器 00:] # exit
[真机: ] # vim /tmp/httpd.conf 将端口改为8080
[真机: ] # docker run -it -v /tmp/httpd.cof: /etc/httpd/conf/httpd.conf myos.httpd
[真机: ] #docker exec -it ac /bin/bash
[容器 ac:] # ss -ntulp | grep 8080 发现端口已被改成8080
使用NFS共享存储:
Docker主机挂在共享目录,在将共享目录映射到容器中。
[root@module ~]# rpm -qa | grep nfs-utils 下载NFS软件提供服务
nfs-utils-1.3.0-0.54.el7.x86_64
[root@module ~]# vim /etc/exports
/var/webhome *(rw)
:wq
root@module ~]# mkdir /var/webhome 将/var/webhome共享出去
[root@module ~]# chmod 777 /var/webhome
[root@module ~]# systemctl restart nfs
[root@module ~]# echo Hello world > /var/webhome/index.html
[root@kubenode-01 ]# yum -y install nfs
[root@kubenode-01 ]#showmount -e 192.168.1.100
[root@kubenode-01 ]#mount -t nfs 192.168.1.100:/var/webhome /mnt
[root@kubenode-01 ]#docker run -it docker.io/nginx:latest /bin/bash 进容器加/bin/bash
[root@kubenode-01 ]#docker run -itd -v /mnt:/usr/share/nginx/html docker.io/nginx 启动服务不加
[root@kubenode-01 ]#docker inspect 3e 查看IP地址
[root@kubenode-01 ]#curl -i 172.17.0.2
[root@kubenode-01 tmp]# curl -i 172.17.0.2
HTTP/1.1 200 OK
Server: nginx/1.15.8
…
hellow world
[root@kubenode-2 ]# yum -y install nfs
[root@kubenode-2 ]#showmount -e 192.168.1.100
[root@kubenode-2 ]#mount -t nfs 192.168.1.100:/var/webhome /mnt
[root@kubenode-2 ]# docker run -itd -v /mnt:/var/www/html/ 192.168.1.100:5000/web2:test2 直接使用仓库里的镜像启动容器
[root@kubenode-2 ]#docker inspect 14
[root@kubenode-2 ]# curl -i 172.17.0.3
[root@kubenode-02 ~]# curl -i 172.17.0.3
HTTP/1.1 200 OK
Date: Fri, 26 Jun 2020 14:26:07 GMT
Server: Apache/2.4.6 (CentOS)
…
hellow world
自定义网桥
在docker中利用镜像生成的容器默认是接在docker0上
可以将docker0想象成一个虚拟的交换机
[root@kubenode-01 ~]# docker network ls #查看docker网络
NETWORK ID NAME DRIVER SCOPE
2b4687baca4f bridge bridge local
47cd23c7c75b host host local
80e09e8993fe none null local
[root@kubenode-01 ~]# docker network create --subnet 10.10.10.0/24 docker1 生成docker1为10网段
81d2964dfaf2e87d6b88dcc33be9aac67dbfae84cf9f04f483ef4d2b7446e459
[root@kubenode-01 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
2b4687baca4f bridge bridge local
81d2964dfaf2 docker1 bridge local
…
[root@kubenode-01 ~]# docker run -it --network=docker1 new.io:test 指定网络创建容器
[容器: ]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.10.10.2 netmask 255.255.255.0 broadcast 0.0.0.0
利用docker1网络创建的容器不能与docker0的容器互通,在有网络需求的架构中可以使用这种方法
[root@kubenode-01 ~]# docker network rm docker1 删除
对外发布服务:
- 默认容器可以访问外网
- 但外部网络的主机不可以访问容器内的资源
- 容器的特征是可以把宿主机变成对应的服务
- 我们可以使用-p 参数把容器端口和宿主机的端口做绑定
- -p 宿主机端口:容器端口
- 例如把docker1 变成httpd
- docker run -itd -p 80:80 docker.io/myos:httpd
- 例如把docker1 变成nginx
- docker run -itd -p 80:80 docker.io/nginx:latest
[root@kubenode-01 ~]# docker run -itd -p80:80 docker.io/nginx:latest
61808de85e36d20c6fe85230f1798754d319c08a4f927443ff79f81902a9a47d
[root@kubenode-01 ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.21 netmask 255.255.255.0 broadcast 192.168.1.255
- 使用浏览器访问 192.168.1.21
[root@kubenode-01 ~]# docker run -itd -p8080:80 web2:test 利用端口绑定启动httpd容器- 使用浏览器访问 192.168.1.21
- 使用浏览器访问 192.168.1.21
[root@kubenode-01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
34d68a846541 docker.io/nginx:latest “nginx -g 'daemon off” 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp big_ramanujan
3dd247af8b7f web2:test “/usr/sbin/httpd -DFO” About a minute ago Up About a minute 0.0.0.0:8080->80/tcp big_mclean
谈谈我对docker的理解:
- docker的重点在于镜像的编排,可以把各种服务放到容器中,很轻便
- 利用docker save 保存镜像,或者搭建私有仓库实现批量部署
- 镜像的编排就像盖房子一样,镜像的后端盘都是只读的,利用docker commit 容器ID 镜像:标签 生成新的镜像
- 假如需要部署10台DNS,直接利用dockerfile写一个DNS镜像,在所有机器上执行端docker 的绑定端口将容器的服务寄生在宿主机上
- docker的难点我觉得在于镜像的编排…