那些讓你看起來很牛逼的Docker使用技巧

在使用docker過程當中,咱們常常發現管理維護是一個很複雜過程,由於咱們在使用docker commands的過程當中,咱們只會去使用咱們認爲簡單而且熟悉的命令,然而docker自己實際上是提供給咱們不少便捷且人性化的工具的,若是掌握這些使用技巧,也許你的維護管理工做將會事半功倍,而且給人看起來會很牛逼的樣子。

來源:http://www.jianshu.com/p/0231568ab335

建立容器時傳入環境變量

在實際應用場景中,不管是從安全仍是可配置方面去考慮,不少參數是比較適合用環境變量加載進去的,好比數據庫的鏈接信息,時區,還有字體支持等等,在建立容器的時候其實均可以使用-e 指定key/value進行傳遞環境變量進去。linux

sh-4.2# docker run -itd --name test-env -e TZ='Asia/Shanghai' 172.25.46.9:5001/centos6.8-jdjr-test-app 
ee20b44301e27c16eae63dab243d293054178dd5f819c23d44bd9e534208bb42
sh-4.2# docker exec -it test-env date
2017年 01月 17日 星期二 10:35:17 CST
sh-4.2# date
Tue Jan 17 10:35:21 CST 2017
能夠看到加了時區環境變量的容器已經和宿主機在同一個時區(CST),而且時間和宿主機基本同步

sh-4.2# docker run -itd --name test  172.25.46.9:5001/centos6.8-jdjr-test-app
d6a02874b999ff4eea79e3b302148b42043af01c89a5d31e5d858e0806f9077a
sh-4.2# docker exec -it test date
2017年 01月 20日 星期五 01:43:48 Asia
默認沒有加時區環境變量的容器仍是Asia
調整宿主機和容器的時間差別 首先咱們須要弄清幾個概念:在類unix系統中有硬件時鐘與系統時鐘,硬件時鐘是指主機板上的時鐘設備,也就是一般可在BIOS畫面設定的時鐘,系統時鐘則是指kernel中的時鐘。unix以及linux系統時間是從格林威治時間到當前的秒數,即1970年1月1日凌晨零點零分零秒到當前的時間,全球都同樣,這是絕對值;而時區則是因爲地理位置差別、行政區劃致使各地顯示時間的差別,爲了克服時間上的混亂,規定將全球劃分爲24個時區,咱們國家眷於東八區標識爲CST。 所以,對於 Docker 容器而言,根本不存在宿主和容器的時間差別問題,由於他們使用的是同一個內核、同一個時鐘,兩者徹底同樣,因此根本不存在同步問題。通常來講這個問題是由時區致使的,可使用date命令查看下容器當前的時間時區是啥。UTC(通用協調時)表示使用的是國際標準0時區,UTC與格林尼治平均時(GMT, Greenwich Mean Time)同樣,都與英國倫敦的本地時相同。CST表示中國標準時間時區通常是中國上海"Aisa/Shanghai",也就是說UTC和CST相差了8個小時。
解決辦法:
建立容器的時候,使用-e 將時區信息傳入到容器內部。
sh-4.2# docker run -itd --name test-env -e TZ='Asia/Shanghai' images
指定容器的rootfs的大小 在使用docker的過程當中,會發現cpu和memory能夠很隨意的動態調整,可是默認的rootfs倒是不能隨意調整的,默認是10g大小,固然若是對於數據有需求,能夠經過掛載voulme進行擴展存儲。若是用戶執意想要調整rootfs的大小,在docker1.12版本默認提供了兩種方式:在啓動docker 的時候加載參數--storage-opt dm.basesize=40G用來調整默認容器的rootfs大小;在建立容器的時候使用參數--storage-opt size=70G來設置改容器的rootfs大小。 喜訊:在docker最近發佈的1.13版本中,支持了磁盤的配額,不過還未測試
sh-4.2# docker run -itd --name volume-test --storage-opt size=70G 172.25.46.9:5001/centos6.8-jdjr-test-app
18d47e69802aa84df00182885b256c50ebc56e15d8e6990fc1e187ffe254171e

sh-4.2# docker exec -it volume-test df -H | grep rootfs
rootfs                 76G  1.5G   74G   2% /
sh-4.2# docker exec -it test-env df -H | grep rootfs
rootfs                 11G  1.5G  9.3G  14% /

快速管理容器和鏡像

在docker中刪除容器須要指定容器名或者容器id,可是在容器比較多,而且狀態不一的狀況下刪除容器仍是須要走下心的。不過好處是docker ps默認提供了不少好用的功能,能夠很方便地管理容器(建立容器的時候若是加上label後更方便哦)。nginx

原理:先用docker ps -a -q 輸出全部容器的container id(-f 表示過濾參數或者輸出格式),而後做爲docker rm 的參數進行批量刪除
輸出全部容器的name:
sh-4.2# docker ps --format='{{.Names}}'
test-env
test-args
test-run
輸出全部容器名包含test的容器,並打印容器名
sh-4.2# docker ps -f name=test --format='{{.Names}}'
test-env
test-args
test-run
查看退出狀態的容器,並打印容器名
sh-4.2# docker ps -f status=exited --format="{{.Names}}"
thirsty_brahmagupta
clever_mestorf
hopeful_morse
stoic_morse
elated_williams
tender_jepsen
reverent_mirzakhani

刪除全部容器:
sh-4.2# docker rm -f -v $(docker ps -a -q)
刪除/啓動全部退出的容器:
sh-4.2# docker rm/start $(docker ps -qf status=exited)
刪除全部鏡像:
sh-4.2# docker rmi $(docker images -q)

查看懸掛鏡像:
sh-4.1# docker  images -qf dangling=true

只查看鏡像或者容器指定的信息(在docker1.10以後才支持的)

只列出鏡像的id以及倉庫名稱:
sh-4.2# docker images --format "{{.ID}}: {{.Repository}}"
67591570dd29: centos
0a18f1c0ead2: rancher/server

只列出容器的相關id,image,status和name
sh-4.2# docker ps --format "{{.ID}}: {{.Image}} : {{.Status}} : {{.Names}}"
66b60b72f00e: centos : Up 7 days : pensive_poincare
或者本身從新定義列,就和原生差很少:
sh-4.2# docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}"
CONTAINER ID        IMAGE                                         STATUS              NAMES
66b60b72f00e        centos                                        Up 7 days           pensive_poincare
注意:其實上面的--format利用的就是go語言中的模版語法,全部容器的組織信息都在結構體中:
*formatter.containerContext
容器label的使用 在實際運維過程當中,大量的容器可能會一些運維上的挑戰,經過使用label,能夠很好的將容器分類。label貫穿於docker的整個過程。 這個label能夠做爲你區分業務,區分模板各類區分容器的標識,經過標識,能夠將容器更好的進行分組

sh-4.2# docker run -itd --name volume-test --storage-opt size=70G --label zone=test 172.25.46.9:5001/centos6.8-jdjr-test-app
c3772397e58e663095c2c0fd8d688b3d41b494097999ec2b6d6b7c509d23a138
建立容器的時候定義一個label,表示該容器在test這個區域
使用定義的label進行快速檢索容器,並進行下一步操做(好比刪除啦,更新啦)
sh-4.2# docker ps -qf label=zone=test
c3772397e58e
sh-4.2# docker ps -f label=zone=test --format='{{.Names}}'
volume-test

快速查看容器的相關配置信息

查看容器的devicemapper設備:
sh-4.2# docker inspect -f '{{.GraphDriver.Data.DeviceName}}' nginx 
docker-8:1-67411759-7c9d6d3327b02659c81bcb70bf6a4c7a45df6a589af2a2d42a387dc0e90d4913
查看容器的PID:
sh-4.2# docker inspect -f '{{.State.Pid}}' nginx 
27521
查看容器name:
sh-4.2# docker inspect -f '{{.Name}}' nginx 
/nginx

使用alias來預約義經常使用的命令

docker管理命令常常須要指定各類參數,經過linux的alias命令將默認的參數預約義起來,能夠很方便的進行管理容器。docker

sh-4.2# alias dockerrm='docker rm -f -v'
sh-4.2# alias dockerexec='docker exec -it'
sh-4.2# alias dockerrmimage='docker rmi'

sh-4.2# dockerrm volume-test
volume-test

sh-4.2# dockerexec volume-test ls
bin   dev  export  lib      media  opt   root  selinux  sys  usr
boot  etc  home    lib64  mnt     proc  sbin  srv      tmp  var
sh-4.2# dockerexec volume-test bash
bash-4.1#

使容器隨着docker daemon的啓動一同啓動

docker run 的時候加參數--restart=always

如何動態修改容器的內存和cpu限制docker1.10以後才支持的動態調整

sh-4.2# dockerexec test-env cat /sys/fs/cgroup/memory/memory.limit_in_bytes
9223372036854775807
sh-4.2# cat /sys/fs/cgroup/memory/memory.limit_in_bytes 
9223372036854775807
能夠看到,默認沒有給容器限制內存,它會共享宿主機的全部內存
動態調整內存爲2014M:
sh-4.2# docker update -m 2014M test-env
test-env
sh-4.2# dockerexec test-env cat /sys/fs/cgroup/memory/memory.limit_in_bytes
2111832064
docker容器中真實用戶的隔離 注意:默認docker容器內部的用戶會繼承宿主機的用戶id,也就是說容器外部有一個uid爲500的用戶test,容器內部有一個uid爲500的用戶admin,容器內部運行的程序若是在宿主機上查看的時候會發現程序的啓動用戶會是外部宿主機的test用戶。 這是由於默認狀況下容器的 user namespace 並未開啓,因此容器內的用戶和宿主用戶共享 uid 空間。容器內的 uid 爲 0 的 root,就被系統視爲 uid=0 的宿主 root,所以磁盤讀寫時,具備宿主 root 同等讀寫權限。
開啓user namespace:
啓動docker的時候加參數--userns-remap=default
https://docs.docker.com/engine/reference/commandline/dockerd/#/daemon-user-namespace-options

在docker container和物理機中雙向拷貝文件

容器內部文件拷貝到宿主機:
sh-4.2# docker cp jupyter-70002111:/home/70002111/教程-研究功能介紹.ipynb .
sh-4.2# ls
Dockerfile  教程-研究功能介紹.ipynb
宿主機文件拷貝到容器:
sh-4.2# docker cp Dockerfile jupyter-70002111:/home/70002111/
sh-4.2# docker exec -it jupyter-70002188 ls 
Dockerfile
向容器內部程序發送signal 注意:在給容器進程發送SIGTERM信號時只會發給主進程,也就是容器內 PID 爲 1 的進程。至於說主進程啓動的那些子進程,徹底看主進程是否願意轉發SIGTERM 給子進程了。因此那些把 Docker當作虛擬機用的,主進程跑了個bash,而後exec 進去啓動程序的,或者來個&讓程序跑後臺的狀況,應用進程必然沒法收到SIGTERM。 還有一種多是在Dockerfile中的CMD那行用的是 shell 格式寫的命令,而不是 exec 格式。在鏡像中使用CMD啓動的容器會加一個 sh -c 來去執行,所以使用 shell 格式寫 CMD 的時候,PID 爲 1 的進程是 sh,而它不轉發信號,因此主程序收不到。 因此在寫CMD哪行命令的時候,最好按照exec格式去寫。 橋接網絡連入下層網絡並使用IPAM (沒有NAT/端口映射) 注意:docker network是1.12版本加進來的,支持了多種網絡插件
$ docker network create \
    -d bridge \
    --subnet=192.168.57.0/24 \
    --ip-range=192.168.57.32/28 \
    --gateway=192.168.57.11 \
    --aux-address DefaultGatewayIPv4=192.168.57.1 \
    -o com.docker.network.bridge.name=brnet \
    brnet
$ brctl addif brnet eth2
$ docker run --net=brnet -it busybox ifconfig

注意其它主機的 --ip-range 和 --gateway 須要作對應調整。

這種拓撲是,容器內 eth0 鏈接 brnet 接口,該接口直接經過 eth2 訪問交換。

Docker查看某個容器綁定的cpu內核

容器內部第一個進程編號通常爲1shell

$ docker exec -it container-name taskset -c -p 1 
pid 1's current affinity list:0-3
相關文章
相關標籤/搜索