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