1.1安装epel源和docker
yum -y install epel-release # 添加epel源
yum list docker --show-duplicates
yum -y install yum-utils
yum list docker-ce --show-duplicates
# 安装docker
yum install docker-ce
systemctl enable docker
systemctl start docker
[root@zabbix-agent ~]# mkdir -p /etc/docker/
[root@zabbix-agent ~]# vim /etc/docker/daemon.json
[root@zabbix-agent log]# cat /etc/docker/daemon.json
{
"graph": "/data/docker",
"storage-driver": "overlay2",
"insecure-registries": ["registry.access.redhat.com","quay.io"],
"registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"],
"bip": "172.168.31.0/24",
"exec-opts": ["native.cgroupdriver=systemd"],
"live-restore": true
}
1.2docker启动一个官方镜像原理
[root@zabbix-agent log]# docker run hello-world
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
为了生成此消息,Docker采取了以下步骤:
1 Docker客户端连接了Docker守护进程。
2 Docker守护进程从Docker Hub中提取了“hello world”图像。
3 Docker守护进程从运行,生成当前正在读取的输出的可执行文件。
4 Docker守护进程将输出流传送到Docker客户端,Docker客户端将其发送去你的终点站。
1.3注册dockerhub
注册:
登陆成功:
镜像结构:
1.4镜像操作
登录docker.hub
[root@zabbix-agent log]# docker login docker.io
查看账户存储位置:
[root@localhost ~]# cat /root/.docker/config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "MTUyMzAzODMyOjEjMwMzgzMg=="
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.12 (linux)"
}
}
通过base64解密字符串得到明文账号信息
[root@localhost ~]# echo "MTUyMzAzODME1MjMwMzgzMg==" | base64 -d
1523xxxx:1523xxxxx
管理登录数据
[root@zabbix-agent log]# cat /root/.docker/config.json
查询镜像
[root@zabbix-agent log]# docker search alpine
从dockerhub拉取到本地默认下载最新的
[root@zabbix-agent log]# docker pull alpine
下载指定的版本or从自己的仓库拉到本地
[root@zabbix-agent log]# docker pull alpine:3.10.3
或
[root@zabbix-agent log]# docker pull docker.io/library/alpine:3.10.1
查看已下载的docker镜像
[root@zabbix-agent log]# docker images
or
[root@zabbix-agent log]# docker image ls
给镜像打标签
[root@localhost ~]# docker tag a24bb4013296 docker.io/152303832/alpine:v3
152303832表示用户名,也就是仓库名
推送镜像
[root@localhost ~]# docker push docker.io/152303832/alpine:v3
The push refers to repository [docker.io/152303832/alpine]
50644c29ef5a: Mounted from library/alpine
v3: digest: sha256:a15790640a6690aa1730c38cf0a440e2aa44aaca9b0e8931a9f2b0d7cc90fd65 size: 528
在打个标签
[root@zabbix-agent log]# docker tag docker.io/152303832/alpine:atest
再推送镜像到远端
[root@zabbix-agent log]# docker push docker.io/152303832/alpine:atest
删除打了标签的镜像
[root@zabbix-agent log]# docker rmi docker.io/152303832/alpine:latest
[root@zabbix-agent log]# docker rmi a24bb4013296 -f
拉取个人仓库镜像
[root@zabbix-agent log]# docker pull 152303832/alpine
2.镜像管理
Docker查看进程
[root@zabbix-agent log]# docker ps -a
[root@zabbix-agent log]# docker run -ti songyifei123/alpine:latest /bin/sh
[root@zabbix-agent log]# docker run --rm songyifei123/alpine:latest /bin/echo hello
[root@zabbix-agent log]# docker run -d --name songyifei songyifei123/alpine:latest /bin/sleep 300
查看宿主机进程
# 查看docker容器在宿主机上运行的进程id
[root@zabbix-agent log]# ps aux|grep sleep|grep -v grep
[root@zabbix-agent log]# docker exec -ti 7bdcfc0aa1bf /bin/sh
停止一个运行的docker容器
[root@zabbix-agent log]# docker start/restart/stop 7bdcfc0aa1bf
删除容器
[root@zabbix-agent log]# docker rm wizardly_bouman
# 批量删除exit状态的所有容器
[root@zabbix-agent ~]# for i in `docker ps -a|grep -i exit|awk '{print $1}'`;do docker rm -f $i;done
导入导出镜像
# 导出镜像
[root@zabbix-agent ~]# docker save 0f3e07c0138f > /tmp/centos.tar
[root@zabbix-agent ~]# docker rmi -f 0f3e07c0138f 删除镜像
# 导入镜像
[root@zabbix-agent ~]# docker load </tmp/centos.tar导入镜像
# 二次修改tag标签
[root@zabbix-agent ~]# docker tag 0f3e07c0138f songyifei/centos:v7.6
查看docker的日志
[root@zabbix-agent ~]# docker logs 42fed44d2f5d
3.docker高级操作
下载nginx镜像
[root@zabbix-agent ~]# docker pull nginx:1.12.2
映射端口
docker run -p 宿主机端口:容器端口
[root@zabbix-agent ~]# docker run --rm --name mynginx -d -p80:80 songyifei123/nginx:1.12.2
挂载数据卷
[root@zabbix-agent html]# mkdir html
[root@zabbix-agent html]# cd html/
[root@zabbix-agent html]# wget www.baidu.com -O index.html
[root@zabbix-agent html]# docker run -d --rm --name nginx_vue -d -p81:80 -v/root/html:/usr/share/nginx/html songyifei123/nginx:1.12.2
传递一个或多个环境变量
[root@zabbix-agent html]# docker run --rm -e E_OPTS=abcdefg songyifei123/nginx:1.12.2 printenv
对nginx镜像二次改造添加yum源和curl:
# 进入到已经运行的容器中
[root@zabbix-agent html]# docker exec -ti nginx_vue /bin/bash
# 添加apt-get国内源
[root@ba6df4b469e4:/# cat /etc/apt/sources.list <<EOF
> deb http://mirrors.163.com/debian jessie main non-free contrib
> deb http://mirrors.163.com/debian jessie-updates main non-free contrib
> EOF
# 更新源,并且下载yum和curl
[root@ba6df4b469e4:/# apt-get update && apt-get install curl -y && apt-get install yum
# 根据当前容器生成对应镜像
[root@localhost ~]# docker commit -p 8a081e7ca97c nginx-yum
# -p :在commit时,将容器暂停
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
152303832/nginx yum 9ab771b2cb25 4 minutes ago 254MB
nginx-yum latest 9ab771b2cb25 4 minutes ago 254MB
nginx latest 2622e6cca7eb 13 days ago 132MB
# 添加标签
[root@localhost ~]# docker tag 9ab771b2cb25 docker.io/152303832/nginx:yum
# 将修改后的镜像推送到docker.io官方仓库中
[root@localhost ~]# docker push docker.io/152303832/nginx:yum
The push refers to repository [docker.io/152303832/nginx]
083e7e00ba29: Pushed
f978b9ed3f26: Mounted from library/nginx
9040af41bb66: Mounted from library/nginx
7c7d7f446182: Mounted from library/nginx
d4cf327d8ef5: Mounted from library/nginx
13cb14c2acd3: Mounted from library/nginx
yum: digest: sha256:2f33216222cbac6a8834abc363f697b4fd00b6925f97659cffd83fc9f9cd05f7 size: 1574
3.1容器的生命周期
检查本地是否存在镜像,如果不存在从远端仓库检索
利用镜像启动容器
分配一个文件系统,并在只读镜像层外挂载一层可读写层
从宿主机配置的网桥接口中桥接一个虚拟接口到容器
从地址池配置一个ip地址给容器
执行用户指定的指令
执行完毕后容器终止
4. Docker file
User/workdir 指令
[root@zabbix-agent dockerfile]# cat Dockerfile
# 以远程仓库中的镜像为基准镜像
FROM docker.io/152303832/nginx:1.12.2
# 使用nginx用户运行
USER nginx
# workdir 相当于CD命令
WORKDIR /usr/share/nginx/html
[root@localhost dockerfile]# docker build . -t docker.io/152303832/nginx:v1_with_user_workdir
[root@localhost dockerfile]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
152303832/nginx v1_with_user_workdir 2511c61da17c 5 minutes ago 254MB
152303832/nginx yum 9ab771b2cb25 4 hours ago 254MB
nginx latest 2622e6cca7eb 13 days ago 132MB
[root@localhost dockerfile]# docker run --rm -it --name mynginx 2511c61da17c /bin/bash
ADD/EXPOSE指令
[root@zabbix-agent dockerfile]# cat Dockerfile
FROM docker.io/152303832/nginx:yum
ADD index.html /usr/share/nginx/html/index.html
# 暴露容器中的端口,一般与-P一起使用,如果使用-p,那么EXPOSE参数将无效
EXPOSE 80
[root@zabbix-agent dockerfile]# docker build . -t 152303832/nginx:yum_index
[root@zabbix-agent dockerfile]# docker run --rm -ti --name nginxindex -P 152303832/nginx:yum_index /bin/bash
# -P 表示将宿主机随机选择任意一个端口映射到容器的80端口
# 进入容器后启动nginx在后台运行,因为前面没有添加参数-d,让nginx服务在后台运行
root@346b431b68f8:/# nginx -g "daemon off"
Run env指令
ENV :环境变量
RUN :在构建时执行可执行命令
[root@zabbix-agent dockerfile]# cat Dockerfile
FROM centos:7
ENV VER 9.11.4
RUN yum install bind-$VER -y
[root@zabbix-agent dockerfile]# docker build . -t bing:v9.11.4_env_run
[root@zabbix-agent dockerfile]# docker run -it --rm bing:v9.11.4_env_run /bin/bash
[root@1f2095862ee0 /]# printenv
CMD 指令
[root@zabbix-agent dockerfile]# cat Dockerfile
FROM centos:7
RUN yum install httpd -y
CMD ["httpd","-D","FOREGROUND"]
# RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包。
# CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换。
[root@zabbix-agent dockerfile]# docker build . -t httpd:test
[root@zabbix-agent dockerfile]# docker run -d --rm --name httpd -p83:80 httpd:test
[root@zabbix-agent dockerfile]# docker ps -a
[root@zabbix-agent dockerfile]# cat Dockerfile
FROM centos:7
ADD entrypoint.sh /entrypoint.sh # 将容器外的文件保存到容器里的目录中
RUN yum -y install epel-release -q -y yum -y install nginx
ENTRYPOINT /entrypoint.sh
# ENTRYPOINT优先级大于在启动容器时添加的linux指令,例如:docker run -it 镜像名 /bin/echo 123,在运行时,ENTRYPOINT的指令会覆盖/bin/echo 123;
[root@zabbix-agent dockerfile]# cat entrypoint.sh
#!/bin/bash
/sbin/nginx -g "daemon off;”
[root@zabbix-agent dockerfile]# chmod +x entrypoint.sh
[root@zabbix-agent dockerfile]# docker build . -t nginx:mynginx
Dockerfile 综合实验
准备dockerfile文件
[root@localhost dockerfile]# cat Dockerfile
FROM docker.io/152303832/nginx:yum
USER root
ENV WWW /usr/share/nginx/html
ENV CONF /etc/nginx/conf.d
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo 'Asia/Shanghai' > /etc/timezone
WORKDIR $WWW
ADD index.html $WWW/index.html
ADD demo.od.com.conf $CONF/demo.od.com.conf
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
备注:
# nginx -g daemon off: 启动nginx服务,并将守护进程关闭,使得nignx在前台运行,让进程一直处理夯住的状态,此处可以在启动容器时加参数-d代替。
Docker 容器启动时,默认会把容器内部第一个进程,也就是pid=1的程序,作为docker容器是否正在运行的依据,如果 docker 容器pid=1的进程挂了,那么docker容器便会直接退出。
Docker未执行自定义的CMD之前,nginx的pid是1,执行到CMD之后,nginx就在后台运行,bash或sh脚本的pid变成了1。
所以一旦执行完自定义CMD,nginx容器也就退出了。
root@4a72cc09c390:/usr/share/nginx/html# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.3 10612 3468 ? Ss 11:42 0:00 nginx: master process nginx -g daemon off;
nginx 21 0.0 0.1 11100 1528 ? S 11:42 0:00 nginx: worker process
root 22 0.0 0.1 3856 2028 pts/0 Ss 11:42 0:00 /bin/bash
root 115 0.0 0.1 7628 1404 pts/0 R+ 11:56 0:00 ps aux
准备index.html
[root@localhost dockerfile]# cat index.html
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
配置nginx的conf配置文件:
[root@localhost dockerfile]# cat demo.od.com.conf
server {
listen 80;
server_name demo.od.com;
root /usr/share/nginx/html;
}
运行容器:
# 构建镜像
[root@localhost dockerfile]# docker build . -t 152303832/nginx:baidu
# 运行容器
[root@localhost dockerfile]# docker run -p80:80 152303832/nginx:baidu
WARNING: IPv4 forwarding is disabled. Networking will not work.
# 出现报错:解决办法参考链接 https://www.cnblogs.com/python-wen/p/11224828.html
# 启动成功
[root@localhost dockerfile]# docker run -it -p80:80 f4de2e3f9b67
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: IPv6 listen already enabled, exiting
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
修改本地hosts文件:
docker的4种网络模型
实现原理
Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。
四类网络模式
bridge模式 –net=bridge (默认为该模式)
1、host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
Host模式如下图所示:
2、container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
Container模式示意图:
Container网络模式
3、none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
None模式示意图:
None网络模式
4、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模式如下图所示: