docker知识点-下篇(2018马哥云计算)

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 <[email protected]>" -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 <[email protected]>"

ENV NGX_DOC_ROOT="/data/web/html/"

ADD index.html ${NGX_DOC_ROOT}
ADD entrypoint.sh /bin/

CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]

# CMD把参数传给脚本,脚本就得接收并执行
cat entrypoint.sh
#!/bin/sh
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,制作失败,其实一般不这么做

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资源.

猜你喜欢

转载自www.cnblogs.com/fawaikuangtu123/p/10420559.html