Docker 實(shí)用技巧總結(jié)
我有機(jī)會建立一個(gè)以Docker為基礎(chǔ)的微服務(wù)架構(gòu)在我現(xiàn)在的工作中,很多人都會分享他們使用Docker的心得,我想我也不會例外。因此我總結(jié)了一些,可能你會在日常使用Docker的時(shí)候會用到。
1. 一臺主機(jī)部署多個(gè)Docker實(shí)例
如果你想運(yùn)行多個(gè)Docker 容器在一臺主機(jī)上,如果要設(shè)置不同的TLS設(shè)置,網(wǎng)絡(luò)設(shè)置,日志設(shè)置和存儲驅(qū)動程序特定的容器,這是特別有用的。例如,我們目前正在運(yùn)行一個(gè)標(biāo)準(zhǔn)設(shè)立兩個(gè)Docker守護(hù)進(jìn)程。一運(yùn)行consul提供DNS解析,并作為群集存儲為其他Docker 容器。
For example:
# start a docker daemon and bind to a specific port
docker daemon -H tcp://$IP:5000 --storage-opt dm.fs=xfs \
-p "/var/run/docker1.pid" \
-g "/var/lib/docker1" \
--exec-root="/var/run/docker1
# and start another daemon
docker daemon -H tcp://$IP:5001 --storage-opt dm.fs=xfs \
-s devicemapper \
--storage-opt dm.thinpooldev=/dev/mapper/docker--vg-docker--pool \
-p "/var/run/docker2.pid" \
-g "/var/lib/docker2" --exec-root="/var/run/docker2"
--cluster-store=consul://$IP:8500 \
--cluster-advertise=$IP:2376
# start a docker daemon and bind to a specific port
dockerdaemon -H tcp://$IP:5000 --storage-opt dm.fs=xfs \
-p "/var/run/docker1.pid" \
-g "/var/lib/docker1" \
--exec-root="/var/run/docker1
# and start another daemon
docker daemon -H tcp://$IP:5001 --storage-opt dm.fs=xfs \
-s devicemapper \
--storage-opt dm.thinpooldev=/dev/mapper/docker--vg-docker--pool \
-p "/var/run/docker2.pid" \
-g "/var/lib/docker2" --exec-root="/var/run/docker2"
--cluster-store=consul://$IP:8500 \
--cluster-advertise=$IP:2376
2. Docker Exec的使用
Docker Exec是一個(gè)很重要很多人都會用到的工具,也許你使用Docker不只是為你的升級,生產(chǎn)和測試環(huán)境,同時(shí)也對本地機(jī)器上運(yùn)行的數(shù)據(jù)庫,服務(wù)器密鑰庫等,這是能夠直接運(yùn)行的容器的上下文中運(yùn)行的命令,非常方便。
我們做了大量的Cassandra,并檢查表是否包含正確的數(shù)據(jù)。如果你只是想執(zhí)行一個(gè)快速CQL查詢,Docker exec 就很贊:
$ docker ps --format "table {{.ID}}\t {{.Names}}\t {{.Status}}"
CONTAINER ID NAMES STATUS
682f47f97fce cassandra Up 2 minutes
4c45aea49180 consul Up 2 minutes
$ docker exec -ti 682f47f97fce cqlsh --color
Connected to Test Cluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 2.2.3 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.
cqlsh>
$ dockerps --format "table {{.ID}}\t {{.Names}}\t {{.Status}}"
CONTAINERID NAMES STATUS
682f47f97fce cassandra Up 2 minutes
4c45aea49180 consul Up 2 minutes
$ dockerexec -ti 682f47f97fce cqlsh --color
Connectedto TestClusterat 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 2.2.3 | CQLspec 3.3.1 | Native protocolv4]
Use HELPfor help.
cqlsh>
或者只是訪問nodetool或鏡像中可用的任何其他工具:
$ docker exec -ti 682f47f97fce nodetool status Datacenter: datacenter1 ======================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns Host ID Rack UN 192.168.99.100 443.34 KB 256 ? 8f9f4a9c-5c4d-4453-b64b-7e01676361ff rack1 Note: Non-system keyspaces don't have the same replication settings, effective ownership information $ dockerexec -ti 682f47f97fce nodetoolstatus Datacenter: datacenter1 ======================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns HostID Rack UN 192.168.99.100 443.34 KB 256 ? 8f9f4a9c-5c4d-4453-b64b-7e01676361ff rack1 Note: Non-systemkeyspacesdon't havethesamereplicationsettings, effectiveownershipinformation
這當(dāng)然可以被應(yīng)用到任何(Client)的工具捆綁在一起的鏡像中。我個(gè)人覺得這樣會比所有客戶端和本地更新更簡單。
3. Docker 的檢查 和JQ
與其說這是一個(gè)Docker技巧,不如說是一個(gè)JQ技巧。如果你沒有聽過JQ,它是一個(gè)在命令行解析JSON的偉大工具。因?yàn)槲覀兛梢圆恍枰褂胒ormat specifier而能夠查看容器里面發(fā)生的一切。
# Get network information:
$ docker inspect 4c45aea49180 | jq '.[].NetworkSettings.Networks'
{
"bridge": {
"EndpointID": "ba1b6efba16de99f260e0fa8892fd4685dbe2f79cba37ac0114195e9fad66075",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
# Get the arguments with which the container was started
$ docker inspect 4c45aea49180 | jq '.[].Args'
[
"-server",
"-advertise",
"192.168.99.100",
"-bootstrap-expect",
"1"
]
# Get all the mounted volumes
11:22 $ docker inspect 4c45aea49180 | jq '.[].Mounts'
[
{
"Name": "a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f",
"Source": "/mnt/sda1/var/lib/docker/volumes/a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true
}
]
# Get network information:
$ dockerinspect 4c45aea49180 | jq '.[].NetworkSettings.Networks'
{
"bridge": {
"EndpointID": "ba1b6efba16de99f260e0fa8892fd4685dbe2f79cba37ac0114195e9fad66075",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
# Get the arguments with which the container was started
$ dockerinspect 4c45aea49180 | jq '.[].Args'
[
"-server",
"-advertise",
"192.168.99.100",
"-bootstrap-expect",
"1"
]
# Get all the mounted volumes
11:22 $ dockerinspect 4c45aea49180 | jq '.[].Mounts'
[
{
"Name": "a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f",
"Source": "/mnt/sda1/var/lib/docker/volumes/a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true
}
]
當(dāng)然,它也能很好的完成查詢其他類型的(Docker-esque) API生成的JSON(e.g Marathon, Mesos, Consul etc.)JQ提供了一個(gè)非常廣泛的API,用于訪問和處理JSON.更多信息可以在這里找到: https://stedolan.github.io/jq/
4. 擴(kuò)展現(xiàn)有容器和在本地注冊
在Docker hub中有大量可以使用的的不同使用場景的鏡像。我們注意到,雖然有很多可用的鏡像,但是很多時(shí)候我們不得對他們做一些修改。比如更好的健康檢查consul,通過系統(tǒng)變量或命令行參數(shù)的其他配置,為更好地設(shè)置或增加我們的集群,這是不容易做到的。如果我們碰到這個(gè)是剛剛創(chuàng)建自己的Docker的鏡像和把它推到我們的本地注冊表。我們通常是這么做的。
比如,我們希望有JQ可在我們的consul 鏡像中這樣我們就可以很方便的檢查我們的服務(wù)是否正常。
FROM progrium/consul USER root ADD bin/jq /bin/jq ADD scripts/health-check.sh /bin/health-check.sh
FROMprogrium/consul USERroot ADDbin/jq /bin/jq ADDscripts/health-check.sh /bin/health-check.sh
我們有了health check scripts and JQ我們就可以從我們自己的consul image做health check了。我們也有一個(gè)本地注冊表運(yùn)行鏡像在創(chuàng)建后,我們只是標(biāo)記生成的鏡像,并將其推到我們的本地注冊表
$ docker build . ... $ docker tag a3157e9edc18 <local-registry>/consul-local:some-tag $ docker push <local-registry>/consul-local:some-tag
$ dockerbuild . ... $ dockertaga3157e9edc18 <local-registry>/consul-local:some-tag $ dockerpush <local-registry>/consul-local:some-tag
現(xiàn)在,它可以提供給我們的開發(fā)者了。并且也可在我們的不同的測試環(huán)境中使用。
5. 訪問遠(yuǎn)程主機(jī)的Docker
Docker的CLI是一個(gè)非??岬墓ぞ?,其中一個(gè)很大的特點(diǎn)是,你可以用它來輕松地訪問多Docker守護(hù)進(jìn)程,即使它們在不同的主機(jī)。你需要做的就是設(shè)置DOCKER_HOST環(huán)境變量指向Docker daemon的監(jiān)聽地址。如果該端口是可以的訪問,你可以直接在遠(yuǎn)程主機(jī)上的Docker,這和你運(yùn)行一個(gè)Docker daemon ,并設(shè)置為通過docker-machine幾乎相同的原理。
$ docker-machine env demo export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://192.168.99.100:2376" export DOCKER_CERT_PATH="/Users/jos/.docker/machine/machines/demo" export DOCKER_MACHINE_NAME="demo"
$ docker-machineenvdemo exportDOCKER_TLS_VERIFY="1" exportDOCKER_HOST="tcp://192.168.99.100:2376" exportDOCKER_CERT_PATH="/Users/jos/.docker/machine/machines/demo" exportDOCKER_MACHINE_NAME="demo"
但你不必限制自己Docker daemons 程通過docker-machine啟動。如果你有你的后臺程序運(yùn)行的控制,以及安全的網(wǎng)絡(luò),你可以很容易地從一臺機(jī)器控制所有的。
6. 簡單的主機(jī)目錄掛載
當(dāng)你正在使用你的容器,你有時(shí)需要得到容器里面的一些數(shù)據(jù)。您可以復(fù)制它,或者通過使用ssh命令。但多數(shù)情況下是最容易的是將一個(gè)主機(jī)目錄添加容器中。可以很容易地通過執(zhí)行下面的命令完成操作:
$ mkdir /Users/jos/temp/samplevolume/ $ ls /Users/jos/temp/samplevolume/ $ docker run -v /Users/jos/temp/samplevolume/:/samplevolume -it --rm busybox $ docker run -v /Users/jos/temp/samplevolume/:/samplevolume -it --rm busybox / # ls samplevolume/ / # touch samplevolume/hello / # ls samplevolume/ hello / # exit $ ls /Users/jos/temp/samplevolume/ hello
$ mkdir /Users/jos/temp/samplevolume/ $ ls /Users/jos/temp/samplevolume/ $ dockerrun -v /Users/jos/temp/samplevolume/:/samplevolume -it --rmbusybox $ dockerrun -v /Users/jos/temp/samplevolume/:/samplevolume -it --rmbusybox / # ls samplevolume/ / # touch samplevolume/hello / # ls samplevolume/ hello / # exit $ ls /Users/jos/temp/samplevolume/ hello
你可以看到我們指定的目錄安裝在容器內(nèi),而且我們把所有的文件都在主機(jī)上,并在容器內(nèi)可見。我們也可以使用inspect查看,看看有什么安裝在哪里。
$ docker inspect 76465cee5d49 | jq '.[].Mounts'
[
{
"Source": "/Users/jos/temp/samplevolume",
"Destination": "/samplevolume",
"Mode": "",
"RW": true
}
]
$ dockerinspect 76465cee5d49 | jq '.[].Mounts'
[
{
"Source": "/Users/jos/temp/samplevolume",
"Destination": "/samplevolume",
"Mode": "",
"RW": true
}
]
我們可以在Docker官網(wǎng)看到更多的特性和使用方 法: https://docs.docker.com/engine/userguide/dockervolumes/
7.添加DNS解析到你的容器
我之前提到過,我們可以通過consul來管理容器。Consul是一個(gè)支持多數(shù)據(jù)中心分布式高可用的服務(wù)發(fā)現(xiàn)和配置共享的服務(wù)軟件,可以為容器提供服務(wù)發(fā)現(xiàn)和健康檢查。對于服務(wù)發(fā)現(xiàn)Consul提供無論是REST API或傳統(tǒng)DNS,他的偉大的之處是,當(dāng)你運(yùn)行一個(gè)具體的鏡像,你可以指定你的容器DNS服務(wù)器。
當(dāng)你有Consul運(yùn)行(或者其它 DNS server)你可以把它添加到您的Docker daemon就像這樣:
docker run -d --dns $IP_CONSUL --dns-search service.consul <rest of confguration>
dockerrun -d --dns $IP_CONSUL --dns-searchservice.consul <restofconfguration>
現(xiàn)在,我們可以解決與Consul的名字注冊的所有容器的IP地址,比如在我們的環(huán)境我們有了一個(gè)cassandra 集群。每個(gè)cassandra將自己注冊名稱為“cassandra”我們的Consul 集群。最酷的是,我們現(xiàn)在只是解決卡cassandra的地址基于主機(jī)名(而不必使用Docker鏈接)
$ docker exec -ti 00c22e9e7c4e bash daemon@00c22e9e7c4e:/opt/docker$ ping cassandra PING cassandra.service.consul (192.168.99.100): 56 data bytes 64 bytes from 192.168.99.100: icmp_seq=0 ttl=64 time=0.053 ms 64 bytes from 192.168.99.100: icmp_seq=1 ttl=64 time=0.077 ms ^C--- cassandra.service.consul ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max/stddev = 0.053/0.065/0.077/0.000 ms daemon@00c22e9e7c4e:/opt/docker$
$ dockerexec -ti 00c22e9e7c4e bash daemon@00c22e9e7c4e:/opt/docker$ pingcassandra PINGcassandra.service.consul (192.168.99.100): 56 databytes 64 bytesfrom 192.168.99.100: icmp_seq=0 ttl=64 time=0.053 ms 64 bytesfrom 192.168.99.100: icmp_seq=1 ttl=64 time=0.077 ms ^C--- cassandra.service.consulpingstatistics --- 2 packetstransmitted, 2 packetsreceived, 0% packetloss round-tripmin/avg/max/stddev = 0.053/0.065/0.077/0.000 ms daemon@00c22e9e7c4e:/opt/docker$
8. Docker-UI是一個(gè)很棒來查看和獲取洞察你容器的方式
使用Docker CLI來查看Docker容器所發(fā)生的一切并不難。很多時(shí)候,雖然你并不需要的Docker CLI的全部功能,但只是想快速瀏覽其中的容器運(yùn)行,看看發(fā)生了什么。Docker UI ( https://github.com/crosbymichael/dockerui )就是一個(gè)這樣偉大的項(xiàng)目,并且他是開源的。

有了這個(gè)工具,你可以看到一個(gè)特定的Docker deamon的容器和鏡像的最重要的東西。
9. Container 不能啟動? Overwrite the Entry Point你只需要從bash啟動。
有時(shí)候一個(gè)容器只是沒有做你想要它做的事情,你已經(jīng)重新創(chuàng)建了Docker 鏡像,你在啟動時(shí)運(yùn)行了幾次,但不知何故,該應(yīng)用程序沒有反應(yīng),然后日志顯示也沒什么有用的信息。最簡單的調(diào)試方法是overwrite the entry point ,看看在容器內(nèi)部發(fā)生的一切,查看文件權(quán)限是否正確??截愡M(jìn)入鏡像的文件是否正確,或者任何其它可能出現(xiàn)的錯(cuò)誤。幸運(yùn)的是,Docker有這樣做的一個(gè)簡單的解決方案。你可以從一個(gè)選擇的入口點(diǎn)啟動你的容器:
$ docker run -ti --entrypoint=bash cassandra root@896757f0bfd4:/# ls bin dev etc lib mediaopt root sbin sys usr boot docker-entrypoint.sh home lib64 mntproc run srv tmp var root@896757f0bfd4:/#
$ dockerrun -ti --entrypoint=bashcassandra root@896757f0bfd4:/# ls bin dev etc libmediaopt root sbin sys usr boot docker-entrypoint.sh home lib64 mntproc run srv tmp var root@896757f0bfd4:/#
10. 監(jiān)聽一個(gè)容器的事件:
當(dāng)你編寫自己的腳本,或者只是想了解發(fā)生了什么,你可以Docker event command運(yùn)行你的鏡像,為此編寫腳本很容易。

這是我們沒有使用Docker Compose 和Swarm yet和Docker 1.9網(wǎng)絡(luò)層 特性的情況,Docker一個(gè)很酷的工具,有一套偉大的工具。在未來希望Docker越來越好,我也會給大家展示一些Docker更酷的東西。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
Docker部署Apollo的實(shí)現(xiàn)步驟
眾所周知分布式配置中心在目前也可以說是企業(yè)中項(xiàng)目的標(biāo)配了,本文主要介紹了Docker 部署Apollo的實(shí)現(xiàn)步驟,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02
使用Docker容器運(yùn)行Mysql實(shí)戰(zhàn)記錄
這篇文章主要給大家介紹了關(guān)于使用Docker容器運(yùn)行Mysql的相關(guān)資料,助大家更好的理解和學(xué)習(xí)使用docker,感興趣的朋友可以了解下,需要的朋友可以參考下2023-09-09
Docker刪除某個(gè)鏡像的實(shí)現(xiàn)方法
在使用 Docker 時(shí),經(jīng)常需要刪除不再需要的鏡像、容器和卷,以釋放存儲空間,本文主要介紹了Docker刪除某個(gè)鏡像的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02
Docker?容器跨主機(jī)通信?overlay的詳細(xì)步驟
Overlay網(wǎng)絡(luò)通過VXLAN技術(shù)創(chuàng)建虛擬網(wǎng)絡(luò),實(shí)現(xiàn)不同主機(jī)上容器的邏輯連接,支持跨主機(jī)通信,具有擴(kuò)展性、隔離性和靈活性,適用于大規(guī)模容器化部署2024-10-10
Docker網(wǎng)絡(luò)配置(橋接網(wǎng)絡(luò)和自定義網(wǎng)絡(luò))自定義網(wǎng)絡(luò)設(shè)置ip方式
這篇文章主要介紹了Docker網(wǎng)絡(luò)配置(橋接網(wǎng)絡(luò)和自定義網(wǎng)絡(luò))自定義網(wǎng)絡(luò)設(shè)置ip方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01

