Docker commit
参考官方文档https://docs.docker.com/engine/reference/commandline/commit/ docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]] -a :提交的镜像作者 -c :使用Dockerfile指令来创建镜像 -m :提交时的说明文字 -p :在commit时,将容器暂停 root@docker:~# docker commit -a "lvxinjie.cn" -m "my mysql" a404c6c174a2 mysql:v1 sha256:37af1236adef1544e8886be23010b66577647a40bc02c0885a6600b33ee28057 root@docker:~# docker images mysql:v1 REPOSITORY TAG IMAGE ID CREATED SIZE mysql v1 37af1236adef
Docker理念
将运用与运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望是持久化的 容器之间希望有可能共享数据 docker容器产生的数据,如果不能通过docker commit生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没了 所以引出数据卷
什么是数据卷
类似redis里面的rdb和aof文件 数据共享和数据持久化
数据卷特点
数据卷可在容器之间共享或重用数据
卷中的更改可以直接生效
数据卷中的更改不会包括在镜像的更新中
数据卷的生命周期一直持续到没有容器使用它为止
添加数据卷
命令添加 DockerFile 添加 注:下面将深入讲解DockerFile
命令添加
docker run -it -v /宿主机绝对路径:/容器内路径 镜像名 [root@docker ~ ]# docker run -it -v /data:/data centos [root@b9452b2d107d /]# ll -d /data/ drwxr-xr-x 2 root root 6 5月 10 11:06 /data/ [root@b9452b2d107d /]# exit exit [root@docker ~ ]# ll -d /data drwxr-xr-x 2 root root 6 5月 10 11:06 /data/ 注:此data目录若不存在,则自动创建
查看数据是否挂载成功
[root@docker ~ ]# df -h 文件系统 容量 已用 可用 已用% 挂载点 /dev/sda3 20G 3.2G 17G 17% / devtmpfs 477M 0 477M 0% /dev tmpfs 488M 0 488M 0% /dev/shm tmpfs 488M 7.7M 480M 2% /run tmpfs 488M 0 488M 0% /sys/fs/cgroup /dev/sda1 197M 102M 95M 52% /boot tmpfs 98M 0 98M 0% /run/user/0 overlay 20G 3.2G 17G 17% /var/lib/docker/overlay2/02cb0e7ea8ee17895f6d697eaee60507695fc59d4a76cbec9ba14f1d4f861fb8/merged
容器和宿主机之间数据共享
容器停止后,主机修改后数据是否同步
启动带入权限
docker run -it -v /宿主机绝对路径:/容器内路径:ro 镜像名 ro --> read only
DockerFile添加
# 根下新建data文件夹斌进入 mkdir /data cd /data # 可在dockerfile使用VOLUME指令给镜像添加一个或多个数据库 VOLUME["/data1","/data2","/data3"] # file构建 # 开始编写dockerfile $ vim Dockefile FROM centos VOLUME ["/data1","/data2"] CMD echo "file is ok --------success" CMD /bin/bash # build生成镜像 --> 获得新镜像 docker build -f /data/Dockerfile -t ajie/centos . # run 容器 docker run -it ajie/centos /bin/bash 注:若启动容器后提示permission denied 在挂载目录后面夹入 --privilegd=true
数据卷容器
命名的容器挂载数据卷,其它容器挂载这个(父容器)实现数据共享,挂载数据卷的容器称之为数据卷容器
小测试
dc01 dc02 dc03 虚拟化三台步骤如下
先启动父容器dc01
[root@docker /data ]# docker run -it --name dc01 ajie/centos [root@56661c67e139 /]# cd /data2 [root@56661c67e139 data2]# touch test2.txt [root@docker /data ]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 56661c67e139 ajie/centos "/bin/sh -c /bin/bash" About a minute ago Up About a minute dc01
dc02/dc03继承dc01
[root@docker /data ]# docker run -it --name dc02 --volumes-from dc01 ajie/centos [root@4e7ea72ceb06 /]# cd data2 [root@4e7ea72ceb06 data2]# ls test2.txt [root@4e7ea72ceb06 data2]# touch test02.txt [root@docker /data ]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4e7ea72ceb06 ajie/centos "/bin/sh -c /bin/bash" About a minute ago Up About a minute dc02 56661c67e139 ajie/centos "/bin/sh -c /bin/bash" 5 minutes ago Up 5 minutes dc01 [root@docker ~ ]# docker run -it --name dc03 --volumes-from dc01 ajie/centos [root@8034ec2956fc /]# cd /data2/ [root@8034ec2956fc data2]# ls test02.txt test2.txt [root@8034ec2956fc data2]# touch dc03.txt [root@8034ec2956fc data2]# ls dc03.txt test02.txt test2.txt [root@docker ~ ]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8034ec2956fc ajie/centos "/bin/sh -c /bin/bash" 46 seconds ago Up 45 seconds dc03 4e7ea72ceb06 ajie/centos "/bin/sh -c /bin/bash" 2 minutes ago Up 2 minutes dc02 56661c67e139 ajie/centos "/bin/sh -c /bin/bash" 6 minutes ago Up 6 minutes dc01
回到dc01可以看到02/03各自添加的都能共享
[root@docker ~ ]# docker attach dc01 [root@56661c67e139 data2]# ls dc03.txt test02.txt test2.txt
删除dc01 dc02修改后dc03能否访问
[root@docker ~ ]# docker rm -f dc01 [root@docker ~ ]# docker attach dc02 [root@4e7ea72ceb06 data2]# ls dc03.txt test02.txt test2.txt [root@4e7ea72ceb06 data2]# touch dc02.txt [root@docker ~ ]# docker attach dc03 [root@8034ec2956fc data2]# ls dc02.txt dc03.txt test02.txt test2.txt
新建dc04继承dc03后在删除dc03(动手操作一下)
# code
结论;容器之间的配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止
什么是DockerFile?
DockerFile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本 类似ansible剧本,有内置命令
构建三步骤
编写dockerfile文件 docker build docker run
文件格式
FROM centos:7 ENV container docker MAINTAINER The CentOS Project <cloud-ops@centos.org> RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \ rm -f /lib/systemd/system/multi-user.target.wants/*;\ rm -f /etc/systemd/system/*.wants/*;\ rm -f /lib/systemd/system/local-fs.target.wants/*; \ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ rm -f /lib/systemd/system/basic.target.wants/*;\ rm -f /lib/systemd/system/anaconda.target.wants/*; VOLUME [ "/sys/fs/cgroup" ] CMD ["/usr/sbin/init"]
构建过程解析
内部基础知识
每条保留字指令都必须为大写字母且后面要跟随至少一个参数 按照指定从上到下,顺序执行 # 表示注释 每条指令都会创建一个新的镜像层,并对镜像进行提交
流程
docker 从基础镜像运行一个容器 执行一条指定并对日前作出修改 执行类似docker commit 的操作提交一个新的镜像层 docker 再基础刚提交的镜像运行一个新容器 执行dockerfile中的下一条指令直到所有的指令都执行完成
总结
从应用软件的角度看,DockerFile,Docker镜像与Docker容器分别代表软件的三个不同阶段 DcokerFile是软件的原材料 Docker镜像是软件的交付品 Docker容器则可以认为是软件的运行状态 DockerFile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
保留字指令
FROM 基础镜像,当前新镜像是基础那个镜像的 MAINTAINER 镜像维护者的姓名和邮箱地址 RUN 容器构建时需要的运行命令 EXPOSE 当前容器对外暴露的端口 WORKDIR 指定在创建容器后,终端默认登录进来的工作目录,一个路径 ENV 用来在构建镜像过程中设置的环境变量 ADD 将宿主机目录下的文件拷贝到镜像里且ADD命令会自动处理URL和tar压缩包 COPY 类似ADD,拷贝文件和目录到镜像中 将从构建上下文目录中<源路径>的文件/目录复制到新的一层镜像内的<目标路径>位置 COPY src dest COPY [ "src","dest" ] VOLUME 容器数据卷,用于数据卷保存和持久化工作 CMD 指定一个容器启动时要运行的命令 Dockerfile中可以有多个CMD命令,但只有最后一个生效,CMD会被docker run之后的参数替换 ENTRYPOINT 指定一个容器启动时要运行的命令 ENTRYPOINT和CMD命令一样,都是在指定容器启动程序及参数 ONBUILD 当构建一个被继承的DockerFile时运行命令,父镜像在被继承后,父镜像的onbuild被触发
案例
Base镜像(scratch) Docker Hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的
自定义镜像mycentos 编写 自定义默认路径 vim功能 ifconfig功能 FROM centos ENV mypath /tmp WORKDIR $mypath RUN yum install vim -y &>/dev/null RUN yum install net-tools -y &>/dev/null EXPOSE 80 CMD /bin/bash 构建 docker build -f /data/mycentos -t name:tag . 运行 docker run -it mycentos:tag 列出镜像的变更历史 docker history mycentos 导出镜像 docker save -o mycentos.tar mycentos 导入镜像 docker load -i xxx
CMD/ENTRYPOINT 镜像案例
制作ip查询 curl -i url i 是请求 CMD演示 vim /data/ip1 FROM centos RUN yum install -y curl &>/dev/null CMD ["curl","-s","baidu.com"] docker build -f /data/ip1 -t ip1 . docker run -it ip1 ENTRYPOINT演示 vim /data/ip2 FROM centos RUN yum install -y curl &>/dev/null ENTRYPOINT ["curl","-s","baidu.com"] docker build -f /data/ip2 -t ip2 . docker run -it ip2 -i
Docker私有仓库
docker registry
docker-harbor
安装docker-compose
yum install -y python2-pip
这里使用pip安装,默认源为国外,可以使用国内加速,相关网站
https://mirrors.tuna.tsinghua.edu.cn/help/pypi/
pip加速操作命令
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -Upip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
继续安装docker-compose
pip install docker-compose
检查
docker-compose version
上传解压docker-harbor
[root@docker01 ~]# cd /opt/ [root@docker01 /opt]# ls harbor-offline-installer-v1.9.0-rc1.tgz [root@docker01 /opt]# tar zxf harbor-offline-installer-v1.9.0-rc1.tgz [root@docker01 /opt]# ls harbor harbor-offline-installer-v1.9.0-rc1.tgz [root@docker01 /opt]# cd harbor/
修改配置文件
[root@docker01 /opt/harbor]# egrep "10.0.1.11|123456" harbor.yml hostname: 10.0.1.11 harbor_admin_password: 123456
安装
[root@docker01 /opt/harbor]# ./install.sh
修改docker信任仓库
[root@docker01 /opt/harbor]# cat /etc/docker/daemon.json { "registry-mirrors": ["http://hub-mirror.c.163.com"], "insecure-registries": ["http://10.0.1.11"] }
重启docker并上传镜像
systemctl restart docker
给镜像打标签并提交到dockerharbor
[root@docker01 /opt/harbor]# docker login 10.0.1.11 Username: zhangya Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded [root@docker01 ~]# docker run -d -p 8080:80 centos_kod:v1 78be80f7c2029b68e8943e38fa99131ec6709f798e63c94afb5a7fdfa4a8047c [root@docker01 ~]# docker ps|grep kod 78be80f7c202 centos_kod:v1 "/bin/bash /init.sh" 15 seconds ago Up 13 seconds 0.0.0.0:8080->80/tcp tender_dirac [root@docker01 ~]# docker commit 78be80f7c202 10.0.1.11/linux/centos_kod:v1 sha256:6bf1e1eef1969bcd4c82472aed945d4dda74a923c0d7dae91e38539676f8c240 [root@docker01 ~/dockerfile/kod]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE 10.0.1.11/linux/centos_kod v1 6bf1e1eef196 13 minutes ago 465MB [root@docker01 /opt/harbor]# docker push 10.0.1.11/linux/centos_kod:v1
在docker-harbor上查看
网页登录 此教程略
其他主机上下载镜像
[root@docker02 ~]# cat /etc/docker/daemon.json { "registry-mirrors": ["http://hub-mirror.c.163.com"], "insecure-registries": ["http://10.0.1.11"], "insecure-registries": ["https://10.0.1.11"] } [root@docker02 ~]# docker pull 10.0.1.11/linux/centos_kod:v1
Docker四种网络模式
实现原理
Docker使用Linux桥接(参考《Linux虚拟网络技术》),在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。
四类网络模式
Docker网络模式 | 配置 | 说明 |
host模式 | –net=host | 容器和宿主机共享Network namespace。 |
container模式 | –net=container:NAME_or_ID | 容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Network namespace。 |
none模式 | –net=none | 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。 |
bridge模式 | –net=bridge | (默认为该模式) |
host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
Host模式如下图所示:
container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
Container模式示意图:
none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
None模式示意图:
bridge模式
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。
bridge模式如下图所示: