01docker簡單使用和配置(容器、映象)
一:容器中執行簡單應用程式
1:hello world
使用docker可以在容器中執行應用程式,使用docker run命令即可。比如下面的命令:
$ docker run ubuntu /bin/echo 'Hello world'
Hello world
docker run命令用於執行一個新的容器,ubuntu指定了該容器執行基於的映象是Ubuntu作業系統映象。指定映象後,Docker首先在Docker主機本地尋找映象,如果找不到則去公共映象倉庫:Docker Hub下載。
接下來,就是指定要在新容器中執行的命令:/bin/echo 'Hello world'。
執行該容器時,Docker建立一個新的Ubuntu作業系統環境,並且在其中執行/bin/echo命令,然後將命令結果輸出到終端。
這種情況下,容器只有在執行命令時處於running狀態,一旦命令執行完成,輸出” Hello world”之後,該容器也就停止運行了。
2:互動式的容器
執行以下命令:
$ docker run -t -i ubuntu /bin/bash
[email protected]:/#
還是以ubunt為基礎映象,這次執行的命令是/bin/bash,在容器中載入一個BASH shell。docker命令中多了兩個選項:-t和-i,-t用於在容器中分配一個新的終端,-i使得使用者可以與容器進行互動。
因此,容器載入後,就可以在容器中執行其他命令了:
[email protected]:/# pwd
/
[email protected]:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[email protected]:/# exit
可見,在容器中,當前處於根目錄下,並且根目錄的結構就是典型的Linux檔案系統。
執行exit退出當前shell,Bash shell程序也就停止了,因此容器也就停止運行了。
3:後臺執行容器
使用以下命令,可以在後臺執行容器:
$ docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147
這裡使用-d選項,將容器置於後臺執行,使其成為daemon程序。
這裡在容器中執行的程式是一個在/bin/sh中,每隔1s列印一次hello world的程式。
執行該命令後,返回的是一個容器ID,利用該容器ID,可以使用docker ps命令,檢視當前處於執行狀態的容器:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1e5535038e28 ubuntu /bin/sh -c 'while tr 2 minutes ago Up 1 minute insane_babbage
可見,剛剛執行的容器處於UP狀態,該命令還列出了剛剛容器的名字:insane_babbage,可以根據該名字,使用docker logs命令可以得到容器的標準輸出。檢視容器中的命令輸出:
$ docker logs insane_babbage
hello world
hello world
hello world
. . .
使用docker stop命令,可以停止該容器:
$ docker stop insane_babbage
insane_babbage
再次使用docker ps命令檢視,發現已經沒有容器運行了:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
二:容器中執行實際應用
1:docker客戶端
每次在shell中使用docker命令,實際上是啟動了一個docker客戶端,docker客戶端連線docker伺服器,由伺服器執行相應的命令。可以使用docker version命令,檢視當前主機上安裝的docker客戶單和docker伺服器版本:
[hh_93_197 /]# docker version
Client:
Version: 1.10.3
API version: 1.22
Go version: go1.5.3
Git commit: 20f81dd
Built: Thu Mar 10 15:39:25 2016
OS/Arch: linux/amd64
Server:
Version: 1.10.3
API version: 1.22
Go version: go1.5.3
Git commit: 20f81dd
Built: Thu Mar 10 15:39:25 2016
OS/Arch: linux/amd64
2:檢視docker命令幫助資訊
可以使用命令docker --help,檢視docker幫助資訊,也可以使用--help,檢視docker子命令的幫助資訊,比如:
[hh_93_197 /]# docker run --help
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
-a, --attach=[] Attach to STDIN, STDOUT or STDERR
--add-host=[] Add a custom host-to-IP mapping (host:ip)
--blkio-weight Block IO (relative weight), between 10 and 1000
--blkio-weight-device=[] Block IO weight (relative device weight)
--cpu-shares CPU shares (relative weight)
--cap-add=[] Add Linux capabilities
--cap-drop=[] Drop Linux capabilities
...
3:在docker中執行web伺服器
使用以下命令,可以在容器中執行一個python的web伺服器:
$ docker run -d -P training/webapp python app.py
這裡使用的映象是training/webapp,其中包含了簡單的Python flask web應用。-d選項使容器後臺執行,-P選項將容器中的埠對映到主機上的埠,後續會詳細解釋。
4:檢視容器
使用docker ps命令檢視剛剛執行的容器:
[hh_93_197 /]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
026fcbe4b3dd training/webapp "python app.py" 23 hours ago Up 3 seconds 0.0.0.0:32770->5000/tcp stoic_davinci
docker ps命令,加上-l選項,可以列出最後一個啟動的容器,docker ps命令只能列出執行狀態的容器,通過-a選項,可以列出所有狀態的容器。
這裡,在PORTS列下的資訊是;0.0.0.0:32770->5000/tcp,因為在docker run中指定了-P選項,因此docker會將容器內的埠對映到主機的埠上,這裡就是將容器的tcp埠5000對映到主機的32770埠上。因此,訪問主機的32770埠,實際訪問的就是容器中的5000埠(預設的Python flask埠):
使用-p選項,也可以自行指定容器和主機之間的埠對映關係,比如下面的命令:
[hh_93_197 /]# docker run -d -p 80:5000 training/webapp python app.py
該命令就將容器的5000對映到主機上的80埠了:
使用docker port命令,可以檢視容器的埠對映情況:
[hh_93_197 /]# docker port sad_archimedes
5000/tcp -> 0.0.0.0:80
使用docker logs命令檢視容器的日誌:
[hh_93_197 /]# docker logs -f sad_archimedes
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
10.1.80.66 - - [16/Mar/2016 07:41:30] "GET / HTTP/1.1" 200 -
10.1.80.66 - - [16/Mar/2016 07:41:30] "GET /favicon.ico HTTP/1.1" 404 -
10.1.80.66 - - [16/Mar/2016 07:41:33] "GET / HTTP/1.1" 200 -
...
這裡的-f選項,類似於tail -f中的選項。
使用docker top命令,可以檢視容器中執行的程序:
[hh_93_197 /]# docker top sad_archimedes
UID PID PPID C STIME TTY TIME CMD
root 21864 24559 0 15:40 ? 00:00:00 python app.py
可見容器中只運行了python的web應用。
使用docker inspect命令,可以獲得容器的更詳細的資訊,該命令返回一個JSON格式資訊:
[hh_93_197 /]# docker inspect sad_archimedes
[
{
"Id": "a7910dd9cafff213db102d679de6a71b2051f980c6d46c3080870973f39af162",
"Created": "2016-03-16T07:40:27.345500271Z",
"Path": "python",
"Args": [
"app.py"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 21864,
"ExitCode": 0,
"Error": "",
"StartedAt": "2016-03-16T07:40:27.726836748Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:6fae60ef344644649a39240b94d73b8ba9c67f898ede85cf8e947a887b3e6557",
"ResolvConfPath": "/var/lib/docker/containers/a7910dd9cafff213db102d679de6a71b2051f980c6d46c3080870973f39af162/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/a7910dd9cafff213db102d679de6a71b2051f980c6d46c3080870973f39af162/hostname",
"HostsPath": "/var/lib/docker/containers/a7910dd9cafff213db102d679de6a71b2051f980c6d46c3080870973f39af162/hosts",
"LogPath": "/var/lib/docker/containers/a7910dd9cafff213db102d679de6a71b2051f980c6d46c3080870973f39af162/a7910dd9cafff213db102d679de6a71b2051f980c6d46c3080870973f39af162-json.log",
"Name": "/sad_archimedes",
"RestartCount": 0,
"Driver": "devicemapper",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {
"5000/tcp": [
{
"HostIp": "",
"HostPort": "80"
}
]
},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"ShmSize": 67108864,
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"KernelMemory": 0,
"Memory": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": -1,
"OomKillDisable": false,
"PidsLimit": 0,
"Ulimits": null
},
"GraphDriver": {
"Name": "devicemapper",
"Data": {
"DeviceId": "66",
"DeviceName": "docker-8:6-538261252-268466c24d896a48119782e8aaf98fc2acf786ce8db86a806b0bddace665169d",
"DeviceSize": "10737418240"
}
},
"Mounts": [],
"Config": {
"Hostname": "a7910dd9caff",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"5000/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"python",
"app.py"
],
"Image": "training/webapp",
"Volumes": null,
"WorkingDir": "/opt/webapp",
"Entrypoint": null,
"OnBuild": null,
"Labels": {},
"StopSignal": "SIGTERM"
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "b41b21041836349d572454db6822fdd8b1128762ec83a8d2fcad7c31de93fcfc",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"5000/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "80"
}
]
},
"SandboxKey": "/var/run/docker/netns/b41b21041836",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "ef7147d741b0a2da2dc768fd23bd9433436a52bedf5773132cbefb6457fe0077",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "4948e842e58f3fedd25afe97bf292d53d7023ddeb90fefb7825103b56c5251b8",
"EndpointID": "ef7147d741b0a2da2dc768fd23bd9433436a52bedf5773132cbefb6457fe0077",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
}
}
]
還可以返回特定的資訊:
[hh_93_197 /]# docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' sad_archimedes
172.17.0.2
5:容器的匯入和匯出
可以使用docker export命令,將容器匯出到本地檔案:
[hh_93_197 ~]# docker export fa0fecad952f > ubuntu.tar
檢視ubuntu.tar的內容:
可以使用docker import命令,從容器快照檔案中再匯入為映象:
[hh_93_197 ~]# cat ubuntu.tar | docker import - test/ubuntu:v1.0
sha256:50288f29d8ad89d09f0a341201a9118118b7d7314466b2c14cea9184734a1056
[hh_93_197 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test/ubuntu v1.0 50288f29d8ad 9 seconds ago 187.7 MB
6:停止,啟動、刪除容器
使用docker stop命令可以停止容器,使用docker start命令可以啟動容器,使用docker rm命令可以刪除容器,注意刪除之前必須先停止容器。
三:映象
docker中,映象是容器的基礎。每次執行docker run命令時,必須指定要使用的映象。執行容器時,docker首先在docker主機上查詢映象,找不到則去映象倉庫Docker Hub Registry中尋找。
1:列出主機上的映象
使用docker images命令可以列出主機上本地映象:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04 1d073211c498 3 days ago 187.9 MB
busybox latest 2c5ac3f849df 5 days ago 1.113 MB
training/webapp latest 54bb4e8718e8 5 months ago 348.7 MB
一般映象庫儲存著一個映象的多個版本,比如ubuntu映象就有10.04, 12.04, 12.10, 13.04, 13.10和14.04版本。這些版本通過tag來區分,比如:ubuntu:14.04。所以,docker命令中指定映象tag的例子如下:
$ docker run -t -i ubuntu:14.04 /bin/bash
如果不指定tag,則docker使用最新的映象:ubuntu:latest。
2:下載新的映象
使用docker pull命令可以下載映象,比如:
$ docker pull centos
Pulling repository centos
b7de3133ff98: Pulling dependent layers
5cc9e91966f7: Pulling fs layer
511136ea3c5a: Download complete
ef52fb1fe610: Download complete
. . .
Status: Downloaded newer image for centos
3:查詢映象
可以在Dcoker Hub(https://hub.docker.com/)上查詢映象,也可以使用命令docker search來查詢,比如想找所有安裝了Sinatra的映象,可以:
$ docker search sinatra
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
training/sinatra Sinatra training image 0 [OK]
marceldegraaf/sinatra Sinatra test app 0
mattwarren/docker-sinatra-demo 0 [OK]
luisbebop/docker-sinatra-hello-world 0 [OK]
bmorearty/handson-sinatra handson-ruby + Sinatra for Hands on with D... 0
subwiz/sinatra 0
bmorearty/sinatra 0
. . .
像ubuntu這種形式的映象,稱為基或者根映象,它們是由docker公司構建、驗證和支援的。像training/sinatra這樣的映象,是從屬於某個docker社群成員的使用者映象,由該Docker社群成員構建並維護,這些映象總是以建立映象的使用者名稱為字首,比如這裡的training。
想要下載training/sinatra映象,可以這樣:$docker pull training/sinatra
4:建立自己的映象
可以通過以下兩種方式升級和建立映象。
a:可以在某個映象基礎上,建立並提交新的映象;
b:可以通過Dockerfile來指定建立映象的命令;
a:升級並提交一個映象
要升級一個映象,首選需要建立一個基於該映象的容器:
[hh_93_197 /]# docker run -t -i ubuntu /bin/bash
[email protected]:/#
比如這裡在/tmp目錄下建立一個readme.txt,當做升級映象的動作:
[email protected]:/# cd /tmp
[email protected]:/tmp# cat readme.txt
this is my image
然後直接執行exit命令退出,這樣容器就停止了。此時,可以根據該容器,使用docker commit命令建立一個新的映象:
[hh_93_197 /]# docker commit -m "Added readme.txt" -a "hh" 0843755bad78 hh/ubuntu:v1
sha256:554a3b147ad10933c7643c65241f02b87d55bf4342f14a852aefe7ff04344a2e
這裡使用了-m和-a選項。-m選項後跟一個註釋資訊(類似於git的-m命令),-a命令用於指定作者。接下來就是指定根據哪個容器建立映象了,這裡0843755bad78就是該容器的ID,然後就是新映象的名稱和tag:hh/ubuntu:v1,其中包含了新映象的使用者名稱hh,映象的名稱ubuntu,以及映象的tag :v1.
使用docker images命令檢視映象:
[hh_93_197 /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hh/ubuntu v1 554a3b147ad1 3 minutes ago 187.9 MB
docker-whale latest 1b1c047367b4 47 hours ago 247 MB
ubuntu latest 07c86167cdc4 12 days ago 187.9 MB
hello-world latest 690ed74de00f 5 months ago 960 B
docker/whalesay latest 6b362a9f73eb 9 months ago 247 MB
training/webapp latest 6fae60ef3446 10 months ago 348.7 MB
使用新的映象建立一個容器:
[hh_93_197 /]# docker run -i -t hh/ubuntu:v1 /bin/bash
[email protected]:/# cat /tmp/readme.txt
this is my image
可見,該容器中確實是有/tmp/readme.txt檔案的。
b:根據Dockerfile建立映象
使用docker commit建立映象有些麻煩且不易於分享。可以使用docker build命令,根據Dockerfile建立映象。
首先需要建立一個Dockerfile檔案,該檔案包含了構建映象的一系列指令:
[hh_93_197 ~]# mkdir ubuntu_hh
[hh_93_197 ~]# cd ubuntu_hh/
[hh_93_197 ~/ubuntu_hh]# touch Dockerfile
在Dockerfile檔案中,每條指令都建立了映象的一個新的層(映象是分層的),簡單的例子如下:
# This is a comment
FROM ubuntu:latest
MAINTAINER hh
RUN touch /tmp/readme.txt
RUN echo "this is my ubuntu V2" >> /tmp/readme.txt
Dockerfile中,以”#”開頭的是註釋語句,每條指令以一個大寫的宣告開始。第一條FROM指令用於告訴docker新建的映象以哪個映象為基礎,這裡以ubuntu:latest為基礎建立新映象。MAINTAINER用於指定映象的作者。
之後是兩個RUN指令,每條RUN指令用於在映象中執行命令,這裡首先是新建檔案/tmp/readme.txt,然後將"this is my ubuntu V2"寫入該檔案。
現在,根據該Dockerfile,使用docker build命令建立新映象:
[hh_93_197 ~/ubuntu_hh]# docker build -t hh/ubuntu:v2 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM ubuntu:latest
---> 07c86167cdc4
Step 2 : MAINTAINER hh
---> Running in 249d7e34ce6b
---> b77f4b33c9ab
Removing intermediate container 249d7e34ce6b
Step 3 : RUN touch /tmp/readme.txt
---> Running in 23c8fdeeca89
---> 447a799e19f4
Removing intermediate container 23c8fdeeca89
Step 4 : RUN echo "this is my ubuntu V2" >> /tmp/readme.txt
---> Running in 758d510038a3
---> 450ca66f56da
Removing intermediate container 758d510038a3
Successfully built 450ca66f56da
使用-t選項,指定新映象的作者為hh,映象名稱為ubuntu,tag為v2。而且指定當前目錄作為Dockerfile檔案所在的目錄,當然也可以指定Dockerfile所在目錄的絕對路徑。
執行該命令之後,docker首先upload構建環境:基本上就是構建目錄的內容;接下來就是執行Dockerfile檔案中每一條指令,可以看見每條指令都建立一個新的臨時容器,然後在容器中執行指令(比如:---> Running in 23c8fdeeca89),然後提交容器的變化(跟docker commit類似),生成一個臨時映象(比如:---> b77f4b33c9ab),然後刪除臨時容器(Removing intermediate container 249d7e34ce6b)。
最後,當所有指令執行完成之後,新的映象就構建成功了,這裡的映象ID是450ca66f56da。所有的臨時映象也都被刪除了,使用docker images檢視新建的映象:
[hh_93_197 ~/ubuntu_hh]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hh/ubuntu v2 450ca66f56da 36 seconds ago 187.9 MB
hh/ubuntu v1 554a3b147ad1 27 minutes ago 187.9 MB
docker-whale latest 1b1c047367b4 47 hours ago 247 MB
ubuntu latest 07c86167cdc4 12 days ago 187.9 MB
hello-world latest 690ed74de00f 5 months ago 960 B
docker/whalesay latest 6b362a9f73eb 9 months ago 247 MB
training/webapp latest 6fae60ef3446 10 months ago 348.7 MB
可以根據新建的映象執行一個容器:
[hh_93_197 ~/ubuntu_hh]# docker run -t -i hh/ubuntu:v2 /bin/bash
[email protected]:/# cat /tmp/readme.txt
this is my ubuntu V2
5:更改映象的tag
可以使用docker tag命令更改一個映象的tag,比如:
docker tag 450ca66f56da ouruser/sinatra:devel
使用docker images檢視映象,發現同一個映象ID具有多個標籤:
[hh_93_197 ~/ubuntu_hh]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hh/ubuntu v2 450ca66f56da 28 minutes ago 187.9 MB
ouruser/sinatra devel 450ca66f56da 28 minutes ago 187.9 MB
...
6:映象摘要
使用V2或者更新格式的映象,具有一個叫做摘要的可定址內容的識別符號。只要用於建立映象的輸入不變,則映象的摘要值就是可預期的,列出映象的摘要值,可以在docker images中使用--digests選項:
$ docker images --digests | head
REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
ouruser/sinatra latest sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf 5db5f8471261 11 hours ago 446.7 MB
當從2.0的映象庫push或者pull時,push或pull命令的輸出包含摘要資訊,可以在pull時使用摘要資訊:
$ docker pull ouruser/[email protected]:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf
也可以在create、run和rmi命令中,以及Dockerfile中的FROM指令中,使用摘要指定映象。
7:映象的匯入和匯出
使用docker save命令,可以匯出映象到本地檔案:
[hh_93_197 ~]# docker save -o ubuntu.tar ubuntu
檢視ubuntu.tar的內容:
使用docker load命令,可以將本地檔案匯入到本地映象庫,比如:
[hh_93_197 ~]# docker load --input ubuntu.tar
或者
[hh_93_197 ~]# docker load < ubuntu.tar
注意:使用者既可以使用 docker load 來匯入映象儲存檔案到本地映象庫,也可以使用docker import 來匯入一個容器快照到本地映象庫。這兩者的區別在於容器快照檔案將丟棄所有的歷史記錄和元資料資訊(即僅儲存容器當時的快照狀態),而映象儲存檔案將儲存完整記錄,體積也要大。此外,從容器快照檔案匯入時可以重新指定標籤等元資料資訊。
8:其他
可以使用docker push命令,將新建的映象上傳至Docker Hub。
可以使用docker rmi命令刪除本地的映象。刪除映象前,需要確認沒有基於該映象的容器執行。