運行一個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服務了