docker网络 存储卷 Dockerfile 私有registry
1.bridge模式
docker run --name bu1 -it --network bridge --rm busybox # 相当于 docker run --name bu1 -it --rm busybox # 默认是bridge docker run --name bu1 -it --network none --rm busybox # 不给容器创建网络 docker run --name bu2 -it -h linux-bu2 --rm busybox # 设置主机名 --dns 114.114.114.114 # 自行设置dns --dns-search ilinux.io # 设置dns搜索域 --add-host www.mageedu.com:1.1.1.1 # 向容器/etc/hosts中添加主机解析 想要让外部能访问容器,添加静态路由是不实用的,因为外部的主机太多了,那么就需要将容器"发布"、"暴露"出去 docker pull nginx docker run --name myweb --rm -p 80 nginx # 映射到物理机的0.0.0.0的随机端口 docker port myweb iptables -t nat -vnL # -p选项,docker自动帮你生成dnat规则 tcp dpt:32768 to:172.17.0.2:80 此时访问http://10.0.0.20:32768/,即可看到nginx页面 docker stop myweb docker run --name myweb --rm -p 10.0.0.20::80 nginx # 映射到物理机的ip+随机端口 docker run --name myweb --rm -p 80:80 nginx # 映射到物理机的0.0.0.0的指定端口 docker run --name myweb --rm -p 10.0.0.20:8080:80 nginx # 映射到物理机的指定ip的指定端口
2.host模式
joined container docker run -it --name b1 --rm busybox docker run -it --name b2 --network container:b1 --rm busybox # 让b2共享b1的UTS:主机名,Net:网络,IPC:进程间通信,其余三个User、Mount、Pid:进程号,还是隔离的 延伸--open container共享宿主机的网络名称空间: docker run -it --name b2 --network host --rm busybox
3.修改默认网络属性
自定义docker0桥的网络属性信息,编辑/etc/docker/daemon.json文件,"bip": "192.168.0.1/24" 最后一项之后不能加逗号,最后一项之后不能加逗号,最后一项之后不能加逗号.
docker守护进程的C/S,其默认仅监听Unix SOcket格式的地址,/var/run/docker.sock;如果想使用TCP套接字:"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"],就可以在其他主机上查看使用了套接字的主机的docker信息:docker -H 10.0.0.20:2375 images
4.创建网桥
docker network --help docker network create -d bridge --subnet "172.27.0.0/24" --gateway "172.27.0.1" mybridge0 # 让镜像使用刚才创建的网桥 docker run --name t1 -it --net mybridge0 busybox # 再起一个使用默认网桥的容器 docker run --name t2 -it --net bridge busybox # 查看宿主机是否打开了地址转发 cat /proc/sys/net/ipv4/ip_forward
默认是不让这俩容器通信的,一个是172.17.0.2,一个是172.27.0.2,因为你设置在不同网段,docker就认为你是想隔离这俩网段.
5.存储卷
docker镜像由多个只读层叠加而成,启动容器时,docker会加载只读镜像并在镜像栈顶部添加一个读写层,如果运行中的容器修改了现有的一个已经存在的文件,该文件会从只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,这就是"写时复制(COW)"机制.Volume的初衷是独立于容器的生命周期实现数据持久化,因此删除容器之时,也不会对未被引用的卷做垃圾回收操作.
两种挂载类型:
a.docker-managed volume # 由docker管理的卷 docker run -it --name bbox1 -v /data busybox docker inspect -f {{.Mounts}} bbox1 b.bind-mount volume # 手动挂载数据卷 docker run -it -v HOSTDIR:VOLUMEDIR --name bbox2 busybox 宿主机上这个目录如果不存在,也会帮你自动创建
通过inspect可以看出两个容器的Mounts,Source、Destination的不同,前者的挂载类型是"volume",-v指定的是目标目录,也就是容器中的目录,源目录会在/var/lib/docker/volumes/下生成一个随机的目录,如果想可控的话,可以提前创建好这个源目录--docker volume create xxx,在挂载时:--mount src=xxx,dst=/var/lib/mysql;
后者的类型是"bind",也可以这样挂载:--mount type=bind,src=xxx,dst=xxx,在这种模式下,两个或者更多的容器,可以共享同一个目录的数据.
延伸:有一个基础支撑容器,它可以不用运行,其它容器运行时,以它为基础,直接共享某个目录.再延伸:joined container--这个基础支撑容器,还可以被用来共享网络,比如一个nginx用它的对外网络,一个tomcat、mysql用它的loop网络.
docker run --name basecon -v /data/basecon/volume:/data/web/html busybox # 一个基础支撑容器 docker run --name nginx --network container:basecon --volume-from basecon -it busybox 网上有这种专门的基础架构支撑容器
6.Dockerfile
# 变量名中的减号:如果这个变量为空或者未设置,则使用默认值 echo ${NAME:-tom} # 变量名中的加号:如果这个变量不为空,则使用默认值 echo ${NAME:+tom}
a.FROM:指定所创建镜像的基础镜像,如果本地不存在,则默认会去Docker Hub下载指定镜像;
b.MAINTAINER:指定维护者信息;
c.COPY:从宿主机复制文件到要创建的镜像中.COPY <src>...<dest>
<src>必须是build上下文中的路径,不能是其父目录中的文件;
如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录本身不会被复制;
如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾;
如果<dest>事先不存在,将会被自动创建.
d.ADD:类似于COPY,ADD支持TAR文件和URL路径
如果是URL路径,则会去网上下载,然后传到指定的镜像目录中,但是不会帮你解压;
如果是本地的压缩文件,则会帮你解压到指定的镜像目录中;
如果注释了对应指令,则也会在要制作的镜像中执行删除操作,一条指令就是一层镜像,要惜字如金.
e.WORKDIR:为指令配置工作目录;
f.VOLUME:创建一个可以从本地主机或其他容器挂载的挂载点;
g.EXPOSE:用于为容器打开指定要监听的端口以实现与外部通信;
需要手动绑定到宿主机的端口上,不会直接暴露,只是说可以暴露这个端口,待暴露;运行容器时-P选项:直接指向该镜像所有要暴露的端口.
h.ENV:用于为镜像定义所需的环境变量,直接成为运行起来的容器的原生环境变量;
初始化镜像为容器时,可以用-e参数修改镜像的环境变量.
ENV DOC_ROOT=/data/web/html/ \ WEB_PACKAGE_VERSION="nginx-1.15.2" COPY index.html ${DOC_ROOT:-/data/web/html/} ADD ${WEB_PACKAGE_VERSION}.tar.gz /usr/local/src/
i.RUN:构建镜像时要执行的命令,cd、tar、mv等;
RUN COMMAND && \ COMMAND # 用yum安装完软件之后,要删除缓存yum clean all,并删除缓存目录,以减小镜像体积.
j.CMD:指定启动容器时默认执行的命令;
大多程序启动时,其父进程是sh,用nohup也可以启动程序,是将程序的父进程变为init,exec command,就是这样的道理.
CMD写的再多,也只执行最后一条,执行默认启动程序时,会在命令前面给你加一个/bin/sh -c,又默认执行了exec,不让你的父进程是/bin/sh,而是内核,所以此时容器内进程的pid为1,所以在使用docker stop container时,该进程可以接收到SIGTERM信号.
Dockerfile中只有CMD时,制作成的镜像,在run这个镜像时,如果后面跟了别的命令,则会覆盖掉默认要执行的命令;
Dockerfile中有ENTRYPOINT时,制作成的镜像,在run这个镜像时,如果后面跟了别的命令,默认命令不会被覆盖掉,反而是将这些命令当成参数添加到后面,想要覆盖默认命令,执行你要想要的命令时,用--entrypoint参数.
CMD第三种方式:和ENTRYPOINT同时存在.作用:给ENTRYPOINT传参.如:
CMD ["/bin/httpd","-f","-h /data/web/html"] ENTRYPOINT ["/bin/sh","-c"] 此时制作镜像,然后运行时给其传参"ls /data/",还是会覆盖CMD
k.healthcheck
EXPOSE 80/tcp HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:{PORT:-80}/
l.ARG
docker run可以向环境变量传值;
docker build想要给环境变量传值,就得在Dockerfile里写上某变量名,并且在外部build时用--build-arg:
docker build --build-arg auyhor="Bob <Bob@qq.com>" -t myweb:v0.3-2 ./
m.ONBUILD
用于在Dockerfile中定义一个触发器,自己构建镜像时不会去执行,别人拿你的镜像作为基础镜像时,会第一步就执行ONBUILD定义的命令(一般用RUN或ADD).
7.做一个能给nginx提供配置文件的Dockerfile
cat Dockerfile # json数组中要使用双引号,注意细节 FROM nginx:1.14-alpine LABEL maintainer="mowang <mowang@163.com>" ENV NGX_DOC_ROOT="/data/web/html/" ADD index.html ${NGX_DOC_ROOT} ADD entrypoint.sh /bin/ EXPOSE 80 CMD ["/usr/sbin/nginx","-g","daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"] # CMD把参数传给脚本,脚本就得接收并执行 cat entrypoint.sh #!/bin/sh mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/www.conf cat > /etc/nginx/conf.d/www.conf <<EOF server { server_name $HOSTNAME; listen ${IP:-0.0.0.0}:${PORT:-80}; root ${NGX_DOC_ROOT:-/usr/share/nginx/html}; } EOF exec "$@" exec的作用:让即将被执行的程序,顶替自己这个脚本,shell脚本退出,exec运行的进程成为主进程. echo "<h1>image from nginx:1.14-alpine</h1>" >> index.html chmod +x entrypoint.sh docker build -t myweb:v0.1-1 ./ docker run --name myweb1 -it --rm myweb:v0.1-1 # 运行 docker exec -it myweb1 /bin/sh # 进入容器,查看配置 wget -O - -q 127.0.0.1 # 可以访问到刚才创建的index.html # 也可以这么验证, docker run --name myweb1 -it --rm -p 10.0.0.20:80:80 myweb:v0.1-1
在浏览器上输出10.0.0.20来访问,第一次构建完成之后,没有访问到指定内容,是因为default.conf的干扰,覆盖其内容,即可获得想要的结果.
8.Docker私有registry
yum info docker-registry docker tag myweb:v0.1-1 linux-docker2:5000/myweb:v0.1-1 docker push linux-docker2:5000/myweb:v0.1-1 会不让推,因为你服务器端做的是http,但客户端是https,所以需要信任 vim /etc/docker/daemon.json "insecure-registries": ["linux-docker2:5000"]添加这一行,并且在最后不要加逗号
9.系统资源限制及验证
a.限制内存
--memory或-m可以单独使用;--memory-swap若想被使用,就必须得有--memory参数;--oom-kill-disable=true时,容器不会因为使用内存过多而被kill.
b.限制CPU
--cpu:分配给容器几个核;--cpuset-cpus:绑定在哪几个核上;--cpu-shares int:在没有限制时,假设起了两个容器,一个shares 1024,一个512,则按照2:1的比例分配cpu资源.