• docker之container


    运行一个container的本身就是开启一个具有独立namespace的进程
      进程有自己的网络,文件系统等
    docker通过run命令来启动一个container
    运行一个container必须要指定一个image作为初始化的文件系统
     
    对于不存在的image,docker会自动去registry里面下载对应的image,然后再运行container
     
    command标志的是在container中实际运行的首进程
      操作系统的0号进程
      在centos7系统上是0号进程systemd

      在容器中是/bin/bash进程,也就是本机host上面的一个普通进程
    如果image里面包含了CMD的命令,那么在启动container的时候,不需要指定command,否则会使用指定的command来覆盖image中的CMD
      也就是这里显示的COMMAND
      容器的状态会随着command的命令执行而改变
     
    前台运行和后台运行:
      默认的container是在前台运行的,会绑定command进程的STDIN、STDOUT、STDERR到console上(在console上展现标准输入、输出和标准错误输出)
        可以通过-d的选项让container运行在后台
      如果是在前台运行,也可以通过-a {STDIN,STDOUT,STDERR}选择需要绑定的IO
        只选择某一个标准展示在console上面
    [root@docker ~]# docker run -t -a stdin centos sh -c "while true;do echo hello world;sleep 2;done"                   
    b7930a6c5c4cdf2b73e24e26f2a8fd801e9eb11a1e28b0a376d180d3fd2e4d4a
    -a stdin:表示只执行了stdin(虽然在前台运行,但是没有指定stdout和stderr所以并没有显示输出)可以通过logs来查看该容器的stdout
    [root@docker ~]# docker logs b7930a6c5c4c
    hello world
    hello world
    通过attach命令可以重新attach一个后台运行的container
      attach可以将后台运行的切换到前台
    在后台运行的情况下,RUN命令会返回一个容器的uuid,唯一标识container
    可以通过docker ps来查看container的uuid和运行信息
    可以通过指定--name的方式来指定container的名字,name必须唯一
     
    inspect:可以查看container的更多信息
      通过docker inspect {container_id}来获取container的更多的信息,包括网络,volume,实际在host上的进程id等信息
     
    log:
      通过logs命令可以看到container中command所指向进程的STDOUT,STDERR数据
      可以进程排错(-d后台运行没有输出到console时,查看)
    # docker run -dt --name mycentos centos sh -c "while true;do echo hello world;sleep 2;done" 

    环境变量:
      通过-e参数,可以在运行container的时候添加系统环境变量
     
    网络设置:
      docker使用bridge桥接的方式来实现container之间以及和外部的通信
    查看本机host的网络信息:
    [root@docker ~]# ifconfig
    docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
            inet6 fe80::42:efff:fe2d:d653  prefixlen 64  scopeid 0x20<link>
            ether 02:42:ef:2d:d6:53  txqueuelen 0  (Ethernet)
            RX packets 1  bytes 76 (76.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 3  bytes 258 (258.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.101.14  netmask 255.255.255.0  broadcast 192.168.101.255
            inet6 fe80::9b70:a5ba:c2d6:d665  prefixlen 64  scopeid 0x20<link>
            ether 00:0c:29:07:65:c0  txqueuelen 1000  (Ethernet)
            RX packets 375314  bytes 497786475 (474.7 MiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 134729  bytes 10091671 (9.6 MiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0x10<host>
            loop  txqueuelen 1  (Local Loopback)
            RX packets 280  bytes 22624 (22.0 KiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 280  bytes 22624 (22.0 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    veth9bd4211: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet6 fe80::5045:f6ff:fef6:da10  prefixlen 64  scopeid 0x20<link>
            ether 52:45:f6:f6:da:10  txqueuelen 0  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 8  bytes 648 (648.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    vethe1ab8ab: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet6 fe80::e0e5:e5ff:fe58:ddec  prefixlen 64  scopeid 0x20<link>
            ether e2:e5:e5:58:dd:ec  txqueuelen 0  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 8  bytes 648 (648.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    上述中veth对应几个container网络
    [root@docker ~]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
    b7930a6c5c4c        centos              "sh -c 'while true..."   5 minutes ago       Up 5 minutes                            stoic_shirley
    8179b8e95e31        centos              "sh -c 'while true..."   15 minutes ago      Up 15 minutes                           mycentos
    两张veth网卡对应两个container容器(正在运行的)
    veth网络都桥接在docker0上(被分配)
     
    network架构:
      在host主机上的一个veth{id}的虚拟网卡和一个container里面的eth0网卡一一映射
      host上的bridge负责把数据流在不同的veth间转发,实现网络的IO
      bridge(docker0)使用RFC1918私有网络,给每一个container分配ip
     
    网络设置
      通过--net参数来修改container的网络设置,默认是bridge的方式
      none表示关闭container的网路连接
      host表示使用主机的网络栈,这个时候host主机不会创建veth虚拟网卡映射到container
        container的网络和主机host的网络在同一网段
    # docker run -t --net host saltstack/ubuntu-14.04 sh -c "while true;do ifconfig;sleep 2;done"
    container:{name|id},使用另外一个container的网络栈
    创建一个容器内的服务,采用本机host的网络ip:
    [root@docker ~]# docker run -d --net host saltstack/ubuntu-14.04 python -m SimpleHTTPServer
    cd07720586501b298c90067e33fb3c099e6e14d91b9de4327026cc2f06321e08
      -d:创建在后台运行
      --net host:创建在本机host网络上
      python -m SimpleHTTPServer:在容器内执行的命令(命令进程不终止,容器状态也不会停止)

    可以看出python的进程已经监听在8000端口上了
      如果不将容器的网络挂在本机host上,那么如何进行访问容器的服务呢?
      将本机host的端口同容器内的端口进行映射,详情看下面端口映射
     
    DNS:
      默认使用host的dns设置
      可以通过--dns的参数来指定container自己的dns配置
     
    端口映射:
      docker通过采用端口映射的方式,允许把内部container的服务端口暴露到外包
      使用-p参数可以指定需要暴露的container的内部端口,在不指定特定的host的对应端口的情况下,docker会自动分配(49000-49900)在一个host上的端口与其映射
      使用-P参数,表示暴露所有在image中通过EXPOSE指定的端口
    [root@docker ~]# docker run -dt -p 8000 saltstack/ubuntu-14.04 python -m SimpleHTTPServer            
    f7d04a31f5a2d6220a70c8dd7d78a5819bd722b3baab9e743c6c098533bd96ec
    -p 8000:表示将容器内的8000端口暴露了出来,由于这里没有明确指定用本机host的哪个端口与之映射,所以这里采用了随机端口
    -p 8000:80 -p 443:443:映射容器中的多个端口(前面本机host端口,后面container端口)
    通过查看container可以看见随机端口与之做了映射,然后访问主机host的这个端口

    下面直接启动一个指定了本机host端口与容器服务端口进行映射:
    [root@docker ~]# docker run -dt -p 80:8000 saltstack/ubuntu-14.04 python -m SimpleHTTPServer       
    a9c3d1c7b6f4319ee34fe726eb5989b7f20bdf4e75e26ef4d5e734665c7efa75

      python -m SimpleHTTPServer:这个服务开启的默认端口为8000

    使用inspect查看整个container信息:

     如果想映射多个端口时:

      -p 8000:80 -p 443:443:映射容器中的多个端口,只需要在后面连接映射本机host端口对应container端口就行
    或者直接-P暴露掉container中的所有端口对应host本机的随机端口
     
    volume绑定:
      通过-v参数,可以把host上的一个目录绑定到container中,允许container对其进行读写
    [root@docker ~]# mkdir test/wadeson -p
    [root@docker ~]# docker run -t -v /root/test:/wadeson saltstack/ubuntu-14.04 sh -c "ls -al /wadeson"
    total 0
    drwxr-xr-x.  3 root root  21 Oct 27 22:09 .
    drwxr-xr-x. 22 root root 257 Oct 27 22:10 ..
    drwxr-xr-x.  2 root root   6 Oct 27 22:09 wadeson
      -v /root/test:/wadeson:将本机host下面的test目录映射到container中下面的wadeson目录
      由于命令执行完成后,container也就消亡了停止了
    docker 数据卷
      -v, --volume list Bind mount a volume
        为container绑定一个数据卷
    [root@docker ~]# docker run -it -v /data -h wadeson saltstack/ubuntu-14.04
    root@wadeson:/# ls
    bin  boot  data  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
      -i:交互模式,直接进入到container容器中
      -t:tty,伪终端
      -h wadeson:指定为container设置hostname
      -v /data:container内的/data为挂载点
    查看data目录:
    root@wadeson:/# ls /data/
    root@wadeson:/# 
    容器中的data目录实际也对应这本机host的某一处目录,使用inspect查看:
      "Mounts": [
                {
                    "Type": "volume",
                    "Name": "71025e4f8325fce175e21861a1fe0d089b9a08760778a8c9c517d6391c0dbceb",
                    "Source": "/var/lib/docker/volumes/71025e4f8325fce175e21861a1fe0d089b9a08760778a8c9c517d6391c0dbceb/_data",
                    "Destination": "/data",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                }

    [root@docker _data]# pwd
    /var/lib/docker/volumes/71025e4f8325fce175e21861a1fe0d089b9a08760778a8c9c517d6391c0dbceb/_data
    [root@docker _data]# ll
    total 0
    这里就是本机host的目录映射到container中的/data目录
    现在在本机host上创建文件,看看容器中的data目录是否存在创建的文件?
    [root@docker _data]# touch wadeson.sh
    [root@docker _data]# ll
    total 0
    -rw-r--r--. 1 root root 0 Oct 26 21:46 wadeson.sh
    返回容器查看:
    root@wadeson:/# ls /data/
    wadeson.sh
    于是验证成功,本机host将某个目录映射到容器中,当不指定host的源目录,那么默认在这里
     
    现在创建一个指定host上一个目录挂载到容器中:
    [root@docker ~]# docker run -it -v /root:/root -h wadeson saltstack/ubuntu-14.04
      将本机host的/root目录挂载到容器中的/root目录
    root@wadeson:/# ls /root/
    anaconda-ks.cfg  docker-ce-17.09.0.ce-1.el7.centos.x86_64.rpm
      在容器中已经成功有了本机host下/root目录的数据
    而默认的挂载点并没有:
    [root@docker volumes]# ll
    total 24
    drwxr-xr-x. 3 root root    19 Oct 26 21:46 71025e4f8325fce175e21861a1fe0d089b9a08760778a8c9c517d6391c0dbceb
    -rw-------. 1 root root 32768 Oct 26 21:39 metadata.db
    如果需要将目录挂载在container中只读:
    docker run -it -v /root:/root:ro -h wadeson saltstack/ubuntu-14.04
    --volumes-from list Mount volumes from the specified container(s)
      从一个指定的容器选择挂载点
    现在有两个容器,都是exited状态,现在启动一个容器,将启动的容器的挂载点选择上面图中的任何一个:
    [root@docker ~]# docker run -it --volumes-from b8c05a805280 -h wadeson saltstack/ubuntu-14.04             
    root@wadeson:/# ls /data/
    root@wadeson:/#
      --volumes-from b8c05a805280:后面接容器名称或者容器id
      相当于两个container共同使用本机host的挂载点
    [root@docker volumes]# ll
    total 24
    drwxr-xr-x. 3 root root    19 Oct 26 21:46 71025e4f8325fce175e21861a1fe0d089b9a08760778a8c9c517d6391c0dbceb
    drwxr-xr-x. 3 root root    19 Oct 26 22:11 f808fc539538ba743c08a852b4b8c4e52c61a33df4c8e52032596385a39b963b
    -rw-------. 1 root root 32768 Oct 26 22:11 metadata.db
    [root@docker volumes]# cd f808fc539538ba743c08a852b4b8c4e52c61a33df4c8e52032596385a39b963b/_data/
    [root@docker _data]# ll
    total 0
      上面就是刚刚新建的(两个container共同使用的挂载点)
     
    容器间通信:
      通过link参数,把container的端口信息暴露到另一个container中,实现container之间的通信
    [root@docker ~]# docker run --name redis -dt redis
    7014723aea605fa4baedb83be8e5f6d528b2fc009aa4379a1694f3131b72b041
      启动一个名为redis的实例,后台运行
      因为有默认的CMD命令,所以创建之后容器在处于运行状态
    [root@docker ~]# docker run --link redis:db -t saltstack/ubuntu-14.04 sh -c "export"
    export DB_ENV_GOSU_VERSION='1.10'
    export DB_ENV_REDIS_DOWNLOAD_SHA='b1a0915dbc91b979d06df1977fe594c3fa9b189f1f3d38743a2948c9f7634813'
    export DB_ENV_REDIS_DOWNLOAD_URL='http://download.redis.io/releases/redis-4.0.2.tar.gz'
    export DB_ENV_REDIS_VERSION='4.0.2'
    export DB_NAME='/wizardly_keller/db'
    export DB_PORT='tcp://172.17.0.2:6379'
    export DB_PORT_6379_TCP='tcp://172.17.0.2:6379'
    export DB_PORT_6379_TCP_ADDR='172.17.0.2'
    export DB_PORT_6379_TCP_PORT='6379'
    export DB_PORT_6379_TCP_PROTO='tcp'
    export HOME='/root'
    export HOSTNAME='192208a0c626'
    export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
    export PWD='/'
    export TERM='xterm'
      该命令创建了将redis的容器的redis服务暴露在另一个container中,利用db这个别名将redis的服务信息暴露给后面这个container的环境变量中,这样后面的container就可以利用变量来连接redis容器的redis服务了
     
     
  • 相关阅读:
    LENGTH()和CHAR_LENGTH()区别
    使用ibatis时 sql中 in 的参数赋值(转)
    数据库类型空间效率探索(五)- decimal/float/double/varchar
    MySQL用命令行复制表的方法
    升讯威微信营销系统开发实践:微信接口的 .NET 封装
    Github开源:Sheng.RabbitMQ.CommandExecuter (RabbitMQ 的命令模式实现)
    开源 & 免费使用 & 打包下载自行部署 :升讯威 周报系统
    开源 & 免费使用 & 打包下载自行部署 :升讯威 周报系统
    GitHub开源:升讯威ADO.NET增强组件 sheng.ADO.NET.Plus V1.3
    [源代码] SailingEase .NET Resources Tool (.NET 多语言资源编辑器)
  • 原文地址:https://www.cnblogs.com/jsonhc/p/7760144.html
Copyright © 2020-2023  润新知