對於執行在後臺的Docker容器,我們運維人員時常是有登陸進去的需求。登陸Docker容器的方式:
1)使用ssh登陸容器。這種方法需要在容器中啟動sshd,存在開銷和攻擊面增大的問題。同時也違反了Docker所倡導的一個容器一個程式的原則。 參考Docker容器學習梳理--SSH方式登陸容器
2)使用自帶命令docker attach登陸容器。命令格式:docker attach container_id。不過docker attach存在的問題是:當多個視窗同時attach到同一個容器時,所有的視窗都會同步的顯示,假如其中的一個視窗發生阻塞時,其它的視窗也會阻塞,docker attach命令可以說是最不方便的進入後臺docker容器的方法。
3)使用自帶命令docker exec登陸容器。命令格式:docker exec -ti container_id /bin/bash。docker exec和docker attach是Docker的原生方法,大多數情況下就使用這兩種命令登陸容器。docker exec命令是在docker1.3之後出現的,比docker attach命令更加方便!兩者之間的區別:
1.Docker attach必須是登陸到一個已經執行的容器裡。需要注意的是如果從這個容器中exit退出的話,就會導致容器停止!!這是極其不方便的! [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2faf24118766 192.168.1.23:5000/tomcat7 "/bin/bash" 4 days ago Up About an hour 0.0.0.0:8888->8080/tcp tomcat [root@localhost ~]# docker attach tomcat [root@2faf24118766 /]# exit //按住ctrl+d退出當前視窗 [root@localhost ~]# docker ps //發現該容器也停止了!! CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2.docker exec登陸容器,注意有兩個引數:-t和-i,這兩個引數很重要! 1)如果只用-i時,由於沒有分配偽終端,看起來像pipe執行一樣。但是執行結果、命令返回值都可以正確獲取。 這種方式可以理解為:在執行的容器上執行新程式!即在宿主機上執行容器裡的命令並檢視到命令結果!這很方便的~但是僅僅使用-i引數無法直接登陸到容器內! [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2faf24118766 192.168.1.23:5000/tomcat7 "/bin/bash" 4 days ago Up About a minute 0.0.0.0:8888->8080/tcp tomcat [root@localhost ~]# docker exec -i tomcat date Sat Apr 1 06:53:46 UTC 2017 [root@localhost ~]# docker exec -i tomcat uptime 06:54:44 up 163 days, 23:28, 0 users, load average: 0.00, 0.01, 0.05 [root@localhost ~]# docker exec -i tomcat /usr/local/tomcat7/bin/startup.sh Tomcat started. 2)如果只使用-t引數,則可以看到一個console視窗,可以在宿主機上執行容器裡的命令並檢視到命令結果,但是這種方式登陸到容器內執行的命令是沒有結果資訊輸出的! [root@localhost ~]# docker exec -t tomcat uptime 07:02:38 up 163 days, 23:36, 0 users, load average: 0.00, 0.02, 0.05 [root@localhost ~]# docker exec -t tomcat pwd / [root@localhost ~]# docker exec -t tomcat /bin/bash //注意,使用-t引數登陸容器,退出當前視窗用的是ctrl+c而不是ctrl+d;而下面使用-ti引數,退出當前視窗使用ctrl+d [root@2faf24118766 /]# uptime //僅僅使用-t引數登陸容器內,發現執行命令後,沒有結果輸出! 3)使用-it時,則和我們平常操作console介面類似,而且不會像attach方式因為退出而導致 整個容器退出。 這種方式可以替代ssh或者nsenter方式,在容器內進行操作。 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2faf24118766 192.168.1.23:5000/tomcat7 "/bin/bash" 4 days ago Up About a minute 0.0.0.0:8888->8080/tcp tomcat [root@localhost ~]# docker exec -t tomcat /bin/bash [root@2faf24118766 /]# exit //按住ctrl+d退出當前視窗 [root@localhost ~]# docker ps //發現容器還在,並沒有因為上面的視窗退出而停止容器! CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2faf24118766 192.168.1.23:5000/tomcat7 "/bin/bash" 4 days ago Up About a minute 0.0.0.0:8888->8080/tcp tomcat 在使用docker exec登陸容器或執行容器中的命令時,最好都帶上-t和-i引數 [root@localhost ~]# docker exec -ti tomcat yum install -y net-tools [root@localhost ~]# docker exec -t -i tomcat ifconfig ---------------------------------------------- 除此之外,docker exec還可以使用-d引數,表示在後臺執行一個程式。如果一個命令需要長時間程式,使用-d引數會很快返回,程式在後臺執行。 這一般用於容器中的命令長時間執行的情況下。 [root@localhost ~]# docker exec -d tomcat yum install -y mysql
4)對於一個已關閉的容器的登陸,可以使用"docker start -ai container"登陸。這種其實就是先啟動容器,然後再進入容器內。
[root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2faf24118766 192.168.1.23:5000/tomcat7 "/bin/bash" 4 days ago Up 9 minutes 0.0.0.0:8888->8080/tcp tomcat [root@localhost ~]# docker stop tomcat tomcat [root@localhost ~]# docker start -i tomcat //引數用-i或-a -i兩個引數都可以 [root@2faf24118766 /]# exit //不過這種方式,在退出當前視窗後,也會導致容器停止! [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5)使用外部工具nsenter登陸容器,該工具和docker exec命令的效果差不多。使用nsenter或docker exec,都可以在容器的上下文(嚴格地說,是名稱空間)中執行任意命令!
1.安裝nsenter nsenter 工具在util-linux包2.23版本後包含。如果系統中 util-linux 包沒有該命令,可以按照下面的方法從原始碼安裝。 [root@localhost ~]# cd /usr/local/src/ [root@localhost src]# curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24; [root@localhost util-linux-2.24]# ./configure --without-ncurses [root@localhost util-linux-2.24]# make nsenter && cp nsenter /usr/local/bin 2.nsenter使用 在使用nsenter命令之前需要獲取到docker容器的程式,然後再使用nsenter工具進去到docker容器中,具體的使用方法如下: # docker inspect -f {{.State.Pid}} 容器名或者容器id //每一個容器都有.State.Pid,所以這個命令除了容器的id需要我們根據docker ps -a去查詢,其他的全部為固定的格式 # nsenter --target 上面查到的程式id --mount --uts --ipc --net --pid // 輸入該命令便進入到容器中 解釋nsenter指令中程式id之後的引數的含義: --mount引數是進去到mount namespace中 --uts引數是進入到uts namespace中 --ipc引數是進入到System V IPC namaspace中 --net引數是進入到network namespace中 --pid引數是進入到pid namespace中 --user引數是進入到user namespace中 在Linux中,最愛簡單的檢視指定命令引數含義的辦法是在終端中輸入: # nsenter --help #會回顯所有與該命令有關的引數 # man nsenter #能查到更加詳細的使用示例和引數說明 [root@localhost ~]# nsenter --help Usage: nsenter [options] <program> [args...] Options: -t, --target <pid> target process to get namespaces from -m, --mount [=<file>] enter mount namespace -u, --uts [=<file>] enter UTS namespace (hostname etc) -i, --ipc [=<file>] enter System V IPC namespace -n, --net [=<file>] enter network namespace -p, --pid [=<file>] enter pid namespace -U, --user [=<file>] enter user namespace -S, --setuid <uid> set uid in user namespace -G, --setgid <gid> set gid in user namespace -r, --root [=<dir>] set the root directory -w, --wd [=<dir>] set the working directory -F, --no-fork do not fork before exec'ing <program> -h, --help display this help and exit -V, --version output version information and exit 例項如下: [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2faf24118766 192.168.1.23:5000/tomcat7 "/bin/bash" 4 days ago Up 23 minutes 0.0.0.0:8888->8080/tcp tomcat [root@localhost ~]# docker inspect -f {{.State.Pid}} tomcat 31356 [root@localhost ~]# nsenter --target 31356 --mount --uts --ipc --net --pid [root@2faf24118766 /]# exit //退出當前視窗,容器不會停止。 logout [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2faf24118766 192.168.1.23:5000/tomcat7 "/bin/bash" 4 days ago Up 27 minutes 0.0.0.0:8888->8080/tcp tomcat 或者: [root@localhost ~]# nsenter -m -u -n -i -p -t 31356 bash [root@2faf24118766 /]# [root@localhost ~]# nsenter -m -u -n -i -p -t 31356 uptime 10:17:08 up 164 days, 2:50, 0 users, load average: 0.00, 0.01, 0.05 [root@localhost ~]# nsenter -m -u -n -i -p -t 31356 free -m total used free shared buff/cache available Mem: 65759080 591904 58142584 419724 7024592 64301784 Swap: 2097148 0 2097148
6)更簡單的是,強烈推薦下載.bashrc_docker,並將內容放到.bashrc中。這個檔案中定義了很多方便使用Docker的命令,比如docker-pid可以獲取某個容器的 PID;而 docker-enter 可以進入容器或直接在容器內執行命令!
如果下面的地址下載.bashrc_docker有問題,可以到百度雲盤上進行下載,下載後放到本機當前使用者的家目錄下,即/root下面,然後執行第二條命令即可! 百度雲盤下載地址:https://pan.baidu.com/s/1YvKmwTsItdGCCVZvM9lMQg 提取密碼:jncy [root@localhost ~]# wget -P ~ https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker [root@localhost ~]# echo "[ -f ~/.bashrc_docker ] && . ~/.bashrc_docker" >> ~/.bashrc; source ~/.bashrc 舉例: [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2faf24118766 192.168.1.23:5000/tomcat7 "/bin/bash" 4 days ago Up 37 minutes 0.0.0.0:8888->8080/tcp tomcat 1)直接使用docker-enter命令進入容器,非常方便! [root@localhost ~]# docker-enter tomcat Last login: Sat Apr 1 10:07:21 UTC 2017 [root@2faf24118766 ~]# exit logout [root@localhost ~]# docker ps //退出登陸視窗後,容器還在! CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2faf24118766 192.168.1.23:5000/tomcat7 "/bin/bash" 4 days ago Up 39 minutes 0.0.0.0:8888->8080/tcp tomcat 以在容器的上下文中執行任意命令!即在宿主機上執行容器裡的命令 [root@localhost ~]# docker-enter tomcat uptime 10:11:05 up 164 days, 2:44, 0 users, load average: 0.05, 0.03, 0.05 ----------------- 注意:在宿主機上使用docker-enter命令執行容器中的命令時,最好後面加上--符號,這樣容器裡的所有存在的命令都可以正常執行。 [root@localhost ~]# docker-enter tomcat -- uptime 10:49:08 up 164 days, 3:22, 0 users, load average: 0.02, 0.02, 0.05 [root@localhost ~]# docker-enter tomcat -- df -h //這條命令如果去掉--符號,就不會順利執行容器中的df -h命令了 Filesystem Size Used Avail Use% Mounted on /dev/mapper/docker-253:0-268868570-9ae66abb2dc10d8d1c4327a41bab376c3684f1c49af91cf6ca2b3a3d58a1d07f 10G 584M 9.5G 6% / tmpfs 32G 0 32G 0% /dev tmpfs 32G 0 32G 0% /sys/fs/cgroup /dev/mapper/centos-root 150G 6.4G 144G 5% /etc/hosts shm [root@localhost ~]# docker-enter tomcat -- cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) 2)使用docker-pid獲取容器PID [root@localhost ~]# echo $(docker-pid tomcat) 31356 [root@localhost ~]# nsenter --target 31356 --mount --uts --ipc --net --pid [root@2faf24118766 /]# 3)還可以使用docker-ip直接獲取容器的ip地址 [root@localhost ~]# docker-ip tomcat 172.17.0.2