Docker容器的创建、启动、停止
容器是独立运行的一个或者一组应用及他们的运行环境。容器是Docker中的一个重要的概念。
Docker容器的两种启动方式
基于镜像新建容器并启动
[root@jk-lx-dev-app01 ~]# docker run centos cal
February 2020
Su Mo Tu We Th Fr Sa
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
我们还可以通过制定参数,启动一个bash交互终端
[root@jk-lx-dev-app01 ~]# docker run -t -i centos /bin/bash
[root@47efd89bf957 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@47efd89bf957 /]# exit
exit
[root@jk-lx-dev-app01 ~]#
参数:
-t :让Docker分配一个伪终端并绑定在容器的标准输入上;
-i :让容器的标准输入保持打开状态
使用docker run命令来启动容器,docker在后台运行的标准操作包括
- 检查本地是否存在指定的镜像,不存在则从公有仓库下载
- 使用镜像创建并启动容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读可写层
- 从宿主机配置的网桥接口中桥接一个虚拟接口到容器中
- 从地址池分批一个IP地址给容器
- 执行用户指定的应用程序
- 执行完毕之后容器被终止
启动、关闭
docker start CONTAINER ID
docker stop CONTAINER ID
docker restart CONTAINER ID
守护态运行
很多时候我们希望容器在后台以守护态运行,此时我们可以添加-d参数来实现(d是deamon的首字母)
例如我们启动centos后台容器,每个一秒打印当天的日历
[root@jk-lx-dev-app01 ~]# docker run -d centos /bin/sh -c "while true;do echo hello docker;sleep 1;done"
[root@jk-lx-dev-app01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9cfcdd86b046 centos "/bin/sh" 14 seconds ago Up 13 seconds hardcore_grothendieck
[root@jk-lx-dev-app01 ~]# docker logs 9cfcdd86b046
hello docker
hello docker
[root@jk-lx-dev-app01 ~]# docker stop 9cfcdd86b046
9cfcdd86b046
进入后台运行的容器
后台进入容器
在启动容器的时候,有时候我们加入了参数-d来启动,这是容器自动进入后台运行,这时候我们想进入容器进行操作应该如何操作?通常我们使用docker attach命令或者nsenter工具进行操作。
docker attach
docker run -idt centos /bin/bash
docker ps
docker attach infalible_brown
[root@jk-lx-dev-app01 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 470671670cac 4 weeks ago 237MB
training/sinatra latest 49d952a36c58 5 years ago 447MB
[root@jk-lx-dev-app01 ~]# docker run -idt centos /bin/bash
128e13c04ae07b38ac06b0ccc9a4283a9efa7c200b5b39c9876d1455e4db2f61
[root@jk-lx-dev-app01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
128e13c04ae0 centos "/bin/bash" 36 seconds ago Up 35 seconds xenodochial_shannon
[root@jk-lx-dev-app01 ~]# docker attach 128e13c04ae0
[root@128e13c04ae0 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
弊端:docker attach命令是同步的,如果多个用户都在用attach到一个容器,那么一个窗口命令就行阻塞,知道当前用户退出,下一个用户才能进行操作。
nsenter命令
nsenter命令在util-linux包2.23版本之后的包含。nsenter可以访问另一个进行的名字空间
安装
目前Centos7以上版本都随系统安装了util-linux相关系统包,直接使用即可
YUM安装
[root@jk-lx-dev-app01 ~]# yum -y install util-linux-2.32.1-17.el8.x86_64
编译安装
[root@jk-lx-dev-app01 ~]# wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz
[root@jk-lx-dev-app01 ~]# tar -zxvf util-linux-xxx.tar.gz
[root@jk-lx-dev-app01 ~]# cd util-linux-xxx
[root@jk-lx-dev-app01 ~]# ./configure --without-ncurses && make nsenter
[root@jk-lx-dev-app01 ~]# cp nsenter /usr/local/bin
nsenter
为了连接到容器,需要知道容器的pid,可以使用nsenter获取
获取PID
方法1:
[root@jk-lx-dev-app01 ~]# docker container top 2235a7bf01d4
UID PID PPID C STIME TTY TIME CMD
root 5817 5800 0 15:53 pts/0 00:00:00 /bin/bash
方法2:
[root@jk-lx-dev-app01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2235a7bf01d4 centos "/bin/bash" 13 minutes ago Up 13 minutes nifty_einstein
[root@jk-lx-dev-app01 ~]# docker inspect -f '{{.State.Pid}} {{.Id}}' $(docker ps -a -q)
PID CONTAINER ID
5817 2235a7bf01d4bef8b19790d9f6ed5462935d7ff450347252b7e53c80be0090aa
方法3:
for i in `docker ps |grep Up|awk '{print $1}'`;do echo \ &&docker top $i &&echo ID=$i; done |grep -A 10 <PID>
root@jk-lx-dev-app01 ~]# for i in `docker ps |grep Up|awk '{print $1}'`;do echo \ &&docker top $i &&echo ID=$i; done
UID PID PPID C STIME TTY TIME CMD
root 5817 5800 0 Feb15 pts/0 00:00:00 /bin/bash
ID=2235a7bf01d4
进入指定PID的容器
[root@jk-lx-dev-app01 ~]# nsenter --target 5817 --mount --uts --ipc --net --pid
[root@2235a7bf01d4 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@2235a7bf01d4 /]# exit
logout
[root@jk-lx-dev-app01 ~]#
查找k8s pod name
docker inspect -f "{{.Id}} {{.State.Pid}} {{.Config.Hostname}}" $(docker ps -q) |grep <PID>
nsenter命令简介
原文链接:https://staight.github.io/2019/09/23/nsenter%E5%91%BD%E4%BB%A4%E7%AE%80%E4%BB%8B/
Man文档链接:http://www.man7.org/linux/man-pages/man1/nsenter.1.html#top_of_page
用途
一个最典型的用途就是进入容器的网络命令空间。相当多的容器为了轻量级,是不包含较为基础的命令的,比如说ip address
,ping
,telnet
,ss
,tcpdump
等等命令,这就给调试容器网络带来相当大的困扰:只能通过docker inspect ContainerID
命令获取到容器IP,以及无法测试和其他网络的连通性。这时就可以使用nsenter命令仅进入该容器的网络命名空间,使用宿主机的命令调试容器网络。
此外,nsenter也可以进入mnt
, uts
, ipc
, pid
, user
命令空间,以及指定根目录和工作目录。
使用
nsenter命令的语法
nsenter [options] [program [arguments]]
options:
-t, --target pid:指定被进入命名空间的目标进程的pid
-m, --mount[=file]:进入mount命令空间。如果指定了file,则进入file的命令空间
-u, --uts[=file]:进入uts命令空间。如果指定了file,则进入file的命令空间
-i, --ipc[=file]:进入ipc命令空间。如果指定了file,则进入file的命令空间
-n, --net[=file]:进入net命令空间。如果指定了file,则进入file的命令空间
-p, --pid[=file]:进入pid命令空间。如果指定了file,则进入file的命令空间
-U, --user[=file]:进入user命令空间。如果指定了file,则进入file的命令空间
-G, --setgid gid:设置运行程序的gid
-S, --setuid uid:设置运行程序的uid
-r, --root[=directory]:设置根目录
-w, --wd[=directory]:设置工作目录
如果没有给出program,则默认执行$SHELL。
示例
运行一个nginx容器,查看该容器的pid:
[root@staight ~]# docker inspect -f {{.State.Pid}} nginx
5645
然后,使用nsenter命令进入该容器的网络命令空间:
[root@staight ~]# nsenter -n -t5645
[root@staight ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
在Kubernetes中,在得到容器pid之前还需获取容器的ID,可以使用如下命令获取:
[root@node1 test]# kubectl get pod test -oyaml|grep containerID
- containerID: docker://cf0873782d587dbca6aa32f49605229da3748600a9926e85b36916141597ec85
或者更为精确地获取containerID:
[root@node1 test]# kubectl get pod test -o template --template='{{range .status.containerStatuses}}{{.containerID}}{{end}}'
docker://cf0873782d587dbca6aa32f49605229da3748600a9926e85b36916141597ec85
导入、导出、删除容器
导出
使用docker export CONTAINER ID 进行导出,导出的为镜像的快照
[root@jk-lx-dev-app01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2235a7bf01d4 centos "/bin/bash" 25 hours ago Up 25 hours nifty_einstein
[root@jk-lx-dev-app01 ~]# docker export 2235a7bf01d4 > ./centos.tar
[root@jk-lx-dev-app01 ~]# ls
centos.tar
[root@jk-lx-dev-app01 ~]#
导入
使用docker import导入
[root@jk-lx-dev-app01 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 470671670cac 4 weeks ago 237MB
training/sinatra latest 49d952a36c58 5 years ago 447MB
[root@jk-lx-dev-app01 ~]# cat centos.tar | docker import - import/centos:v.2.0.1
sha256:3ebf5bc49a719c608c6a806ecb2c25ff2892d672261a3c53b3c2ef2d8588d763
[root@jk-lx-dev-app01 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
import/centos v.2.0.1 3ebf5bc49a71 4 seconds ago 237MB
centos latest 470671670cac 4 weeks ago 237MB
training/sinatra latest 49d952a36c58 5 years ago 447MB
[root@jk-lx-dev-app01 ~]#
导入某个URL的镜像
[root@jk-lx-dev-app01 ~]# docker import http://xxxx.com/image_test.tgz test/images_test
导入方法的区别
docker可以使用docker load来导入镜像,也可以使用docker import来导入一个容器快照到docker镜像。两者的区别在于容器快照将丢弃所有的历史记录和元数据信息,而docker load导入的镜像保存完整的记录,因此要更大一些。
docker import #导入镜像快照,无元数据和完整记录,相对较小
docker load #导入镜像,有元数据和完整记录,相对较大
删除
使用docker rm删除一个处于停止状态的容器
[root@jk-lx-dev-app01 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
39ea01dff236 8b8e4b9c1098 "/bin/sh -c 'yum -qq…" 9 days ago Exited (1) 9 days ago nice_cori
[root@jk-lx-dev-app01 ~]# docker rm 39ea01dff236
39ea01dff236
[root@jk-lx-dev-app01 ~]#
使用docker rm中的-f参数强制删除处于运行状态的容器
[root@jk-lx-dev-app01 ~]# docker start 47efd89bf957
47efd89bf957
[root@jk-lx-dev-app01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2235a7bf01d4 centos "/bin/bash" 25 hours ago Up 25 hours nifty_einstein
47efd89bf957 centos "/bin/bash" 3 days ago Up 9 seconds suspicious_johnson
[root@jk-lx-dev-app01 ~]# docker rm 47efd89bf957
Error response from daemon: You cannot remove a running container 47efd89bf9571fa2f19aca7ab12da8bf3a063ce9f9b279046c794ef2e4d71444. Stop the container before attempting removal or force remove
[root@jk-lx-dev-app01 ~]# docker rm -f 47efd89bf957
47efd89bf957
[root@jk-lx-dev-app01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2235a7bf01d4 centos "/bin/bash" 25 hours ago Up 25 hours nifty_einstein
[root@jk-lx-dev-app01 ~]#