docker 容器的基本操作
查看本地容器的进程:
~]$ docker ps // 只查看“活”的进程 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ~]$ docker ps -a // 查看所有的进程,不管“死”的还是“活”的 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 02a5d6d99ebc hello-world "/hello" 4 days ago Exited (0) 4 days ago zen_torvalds
启动容器(运行镜像)
docker run 是日常用的最频繁的命令之一,同样也是较为复杂的命令之一
命令格式: docker run [OPTIONS] IMAGE [COMMOND] [ARG...]
OPTIONS: 选项
-i 表示启动一个可交互的容器,并持续打开标准输入
-t 表示使用终端关联到容器的标准输入输出上
-d 表示将容器放置在后台运行
--rm 退出后即删除容器
--name 表示定义容器的唯一名称
IMAGE 表示要运行的镜像
COMMOND 表示启动容器时要运行的命令 *
交互式启动一个容器
~]$ docker run -it alpine:latest /bin/sh / # ip add 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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 6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever / # / # cat /etc/issue Welcome to Alpine Linux 3.14 Kernel on an m (l) // 用另一个窗口去查看 docker ps ~]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 03ff62ec1bcf alpine:latest "/bin/sh" 7 seconds ago Up 6 seconds infallible_booth
非交互式启动一个容器:
~]$ docker run --rm alpine:latest /bin/echo hello hello // docker run --rm 在运行完之后,就会在 docker ps -a 中把它给删了,所以在 docker ps -a 中看不到 --rm 的那个进程; 一次性运行的程序适用于 --rm 的 docker run
非交互式启动一个后台容器
~]$ docker run -d --name myalpine alpine:latest /bin/sleep 300 28b43f3bae98100aab4d5e7a2c343ef3f0876c33e8f83fbd600748c2e4bd1866 // -d 参数
查看宿主机进程
~]$ ps aux | grep sleep | grep -v grep root 28755 0.1 0.0 1584 4 ? Ss 08:30 0:00 /bin/sleep 300 // 在宿主机上也能看到 docker 进程
进入容器
通过 exec 命令能进入到一个在 up 状态的容器
~]$ docker run -d --name myalpine1 alpine:latest /bin/sleep 300 cb8cfcb1175b12fc9b66f150a161d4ca7d38c75b52ebf4807b07a3490bebb456 ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cb8cfcb1175b alpine:latest "/bin/sleep 300" 4 seconds ago Up 3 seconds myalpine1 28b43f3bae98 alpine:latest "/bin/sleep 300" 5 minutes ago Exited (0) 45 seconds ago myalpine 03ff62ec1bcf alpine:latest "/bin/sh" 17 hours ago Exited (0) 17 hours ago infallible_booth 02a5d6d99ebc hello-world "/hello" 5 days ago Exited (0) 5 days ago zen_torvalds ~]$ docker exec -it cb8cfcb1175b /bin/sh / # ps aux PID USER TIME COMMAND 1 root 0:00 /bin/sleep 300 7 root 0:00 /bin/sh 14 root 0:00 ps aux / # / # exit // docker exec -it 容器ID
停止容器
命令: docker stop 容器ID
~]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cb8cfcb1175b alpine:latest "/bin/sleep 300" 2 minutes ago Up 2 minutes myalpine1 ~]$ docker stop cb8cfcb1175b cb8cfcb1175b ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cb8cfcb1175b alpine:latest "/bin/sleep 300" 4 minutes ago Exited (137) About a minute ago myalpine1 // 让容器再起来: docker start 容器ID ~]$ docker start cb8cfcb1175b cb8cfcb1175b ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cb8cfcb1175b alpine:latest "/bin/sleep 300" 5 minutes ago Up 3 seconds myalpine1 // 重启容器 docker restart 容器ID或容器name ~]$ docker restart cb8cfcb1175b cb8cfcb1175b ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cb8cfcb1175b alpine:latest "/bin/sleep 300" 7 minutes ago Up 11 seconds myalpine1
提交镜像:
命令: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
// 先起一个容器,让其处于 up 状态 ~]$ docker run -d --name myalpine alpine:latest /bin/sleep 300 ff63956cd33913d3e9609998648b77853ae7c5007643d3d1e2a2757839a9bfc1 ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ff63956cd339 alpine:latest "/bin/sleep 300" About a minute ago Up About a minute myalpine // docker exec 进入 处于 up 状态的 容器 ~]$ docker exec -it ff63956cd339 /bin/sh / # / # ls bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var / # echo hello 1.txt hello 1.txt / # / # ls bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var / # echo hello > 1.txt // 在容器中生成一个文件;这个文件是写在了容器的 可写层 / # / # ls 1.txt bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var / # cat 1.txt hello / # exit // 只要上面的容器还处于 up 状态,那么 1.txt 这个文件在容器中就还存在;如果容器退出了,那么再启动该镜像时,这个容器中就没有 1.txt 这个文件了,因为 1.txt 不在镜像里,它只在容器的可写层。 // 在容器还处于 up 状态时,通过 docker commit 把它固化到容器的只读层。 ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ff63956cd339 alpine:latest "/bin/sleep 300" 2 minutes ago Up 2 minutes myalpine ~]$ docker commit -p ff63956cd339 neomaple/alpine:v3.10.3_with_1.txt sha256:a8d22d6a1dc43b21dc5a80ee3701712849b56eac7483d8c934e5c721137be0d0 ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE neomaple/alpine v3.10.3_with_1.txt a8d22d6a1dc4 5 seconds ago 5.6MB // 生成一个新的镜像 ~]$ docker run -it neomaple/alpine:v3.10.3_with_1.txt /bin/sh / # ls // 新的镜像启动容器后,还会有 1.txt 这个文件 1.txt bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var / # cat 1.txt hello / # exit
导出镜像:
命令: docker save IMAGE-ID > 文件名.tar
~]$ docker save a8d22d6a1dc4 > alpine:v3.10.3_with_1.txt.tar ~]$ ll 总用量 5744 -rw-rw-r-- 1 ec2-user ec2-user 5880320 8月 29 16:06 alpine:v3.10.3_with_1.txt.tar
导入镜像:
命令: docker load < 镜像文件名.tar
~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE neomaple/alpine v3.10.3_with_1.txt a8d22d6a1dc4 7 hours ago 5.6MB alpine latest 021b3423115f 3 weeks ago 5.6MB hello-world latest d1165f221234 5 months ago 13.3kB // 删除镜像 ~]$ docker rmi a8d22d6a1dc4 Untagged: neomaple/alpine:v3.10.3_with_1.txt Deleted: sha256:a8d22d6a1dc43b21dc5a80ee3701712849b56eac7483d8c934e5c721137be0d0 Deleted: sha256:759ef2bae57058f5d502c4cebbb1e16ab6f3ce5192e71cc3bea04e98cc99cf1c // 删除镜像是 docker rmi ;删除容器是 docker rm ~]$ docker load < alpine:v3.10.3_with_1.txt.tar // 把镜像导入进来 6328e474a947: Loading layer [==================================================>] 3.584kB/3.584kB Loaded image ID: sha256:a8d22d6a1dc43b21dc5a80ee3701712849b56eac7483d8c934e5c721137be0d0 ~]$ docker images // 此时发现导入的镜像没有 repository 和 tag REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> a8d22d6a1dc4 7 hours ago 5.6MB ~]$ docker tag a8d22d6a1dc4 neomaple/alpine:v3.10.3_with_1.txt ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE neomaple/alpine v3.10.3_with_1.txt a8d22d6a1dc4 7 hours ago 5.6MB // 运行导入的镜像 ~]$ docker run -it --name neoalpine1 neomaple/alpine:v3.10.3_with_1.txt /bin/sh / # / # ls 1.txt bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var / # exit
所以,可以把容器里面的东西固化到镜像里面;也可以把镜像保存成文件,再把文件导入回镜像
查看容器的日志:
~]$ docker run hello-world 2>&1 >> /dev/null // 2>&1 对于& 1 更准确的说应该是文件描述符 1,而1标识标准输出,stdout。对于2 ,表示标准错误,stderr。2>&1 的意思就是将标准错误重定向到标准输出。这里标准输出已经重定向到了 /dev/null。那么标准错误也会输出到/dev/null。可以把/dev/null 可以看作"黑洞". 它等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到. ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e3abbc174e37 hello-world "/hello" 6 seconds ago Exited (0) 5 seconds ago relaxed_tereshkova // /hello 执行的时候,把它的输出打到了容器里面的标准输出上。 docker log CONTAINER-ID 命令就可以看到容器里面的标准输出是什么 ~]$ docker logs e3abbc174e37 Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. ... // docker logs -f CONTAINER-ID 就相当于 tail -f ,就是不断的打印日志(动态输出)
docker 容器的高级操作
高级操作不是说复杂,而是说太重要了,主要如下:
1、映射端口:
docker run -p 容器外端口:容器内端口
2、挂载数据卷:
docker run -v 容器外目录:容器内目录
3、传递环境变量:
docker run -e 环境变量key=环境变量value
4、容器内安装软件(工具)
yum/apt-get/apt 等
下载 nginx 镜像
~]$ docker pull nginx:1.12.2 ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx 1.12.2 4037a5562b03 3 years ago 108MB ~]$ docker tag 4037a5562b03 neomaple/nginx:v1.12.2 ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE neomaple/nginx v1.12.2 4037a5562b03 3 years ago 108MB
映射端口:
~]$ docker run -d -p81:80 neomaple/nginx:v1.12.2 47b46b379d4c82f17d6be040722dcd703a109f8600cd378e34355825a18787c0 ~]$ netstat -lntup | grep 81 (No info could be read for "-p": geteuid()=1000 but you should be root.) tcp 0 0 0.0.0.0:81 0.0.0.0:* LISTEN ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 47b46b379d4c neomaple/nginx:v1.12.2 "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:81->80/tcp friendly_newton ~]$ curl 127.0.0.1:81 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
挂载数据卷:
挂载:让容器里面的某个目录和我宿主机上的某个目录关联起来 (将宿主机目录挂载到容器里)
~]$ mkdir html ~]$ ll 总用量 5744 -rw-rw-r-- 1 ec2-user ec2-user 5880320 8月 29 16:06 alpine:v3.10.3_with_1.txt.tar drwxrwxr-x 2 ec2-user ec2-user 6 8月 31 16:09 html // 把baidu的首页下载到 html/ 目录 html]$ wget www.baidu.com -O index.html html]$ ll 总用量 4 -rw-rw-r-- 1 ec2-user ec2-user 2381 8月 31 16:11 index.html // 将宿主机的目录 /home/ec2-user/html 挂载到 /usr/share/nginx/html html]$ docker run -d -p82:80 -v/home/ec2-user/html/:/usr/share/nginx/html neomaple/nginx:v1.12.2 b57091793c7fde7d0cfb8fdbb7914a56a42e83553d118aa06a62b9660f10ba54 html]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b57091793c7f neomaple/nginx:v1.12.2 "nginx -g 'daemon of…" 5 seconds ago Up 4 seconds 0.0.0.0:82->80/tcp elastic_tharp html]$ curl 127.0.0.1:82 <!DOCTYPE html> <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html> html]$ docker exec -it b57091793c7f /bin/sh # ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var # cd usr/share/nginx/html # ls index.html # exit
挂载后可以用 docker inspect CONTAINER-ID 命令来查看挂载相关的内容
~]$ docker inspect b57091793c7f ... ... ... "Mounts": [ { "Type": "bind", "Source": "/home/ec2-user/html", "Destination": "/usr/share/nginx/html", "Mode": "", "RW": true, "Propagation": "rprivate" } ],
关于挂载,可看下这篇文章: https://blog.csdn.net/weixin_43756600/article/details/107881903
传递环境变量
~]$ docker run -e E_OPTS=abcde neomaple/nginx:v1.12.2 printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=b544e7ceb135 E_OPTS=abcde NGINX_VERSION=1.12.2-1~stretch NJS_VERSION=1.12.2.0.1.14-1~stretch HOME=/root
容器内安装软件
~]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 47b46b379d4c neomaple/nginx:v1.12.2 "nginx -g 'daemon of…" 2 days ago Up 2 days 0.0.0.0:81->80/tcp friendly_newton ~]$ docker exec -it 47b46b379d4c /bin/bash root@47b46b379d4c:/# root@47b46b379d4c:/# curl bash: curl: command not found // curl 命令不存在 root@47b46b379d4c:/# root@47b46b379d4c:/# tee /etc/apt/source.list << EOF // 修改镜像源 > deb http:mirrors.163.com/debian/ jessie main non-free contrib > deb http:mirrors.163.com/debian/ jessie-updates main non-free contrib > EOF deb http:mirrors.163.com/debian/ jessie main non-free contrib deb http:mirrors.163.com/debian/ jessie-updates main non-free contrib root@47b46b379d4c:/# root@47b46b379d4c:/# apt-get update && apt-get install curl -y // 安装 curl 命令 ... ... ... root@47b46b379d4c:/# curl -k https://www.baidu.com <!DOCTYPE html> <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>'); </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
由于上面的镜像比较重要,后面我们还需要用,所以把上面的镜像进行一下固化
~]$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 47b46b379d4c neomaple/nginx:v1.12.2 "nginx -g 'daemon of…" 2 days ago Up 2 days 0.0.0.0:81->80/tcp friendly_newton ~]$ docker commit -p 47b46b379d4c neomaple/nginx:v1.12.2-with_curl // 固化镜像 sha256:bed9d53d040fb23b854e574772fdcda557ea4de337c2dd2810c46c758390ce1f ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE neomaple/nginx v1.12.2-with_curl bed9d53d040f 7 seconds ago 141MB ~]$ docker push neomaple/nginx:v1.12.2-with_curl // 推到远程仓库 docker hub The push refers to repository [docker.io/neomaple/nginx] 8c9c286306ea: Pushed 4258832b2570: Mounted from library/nginx 683a28d1d7fd: Mounted from library/nginx d626a8ad97a1: Mounted from library/nginx v1.12.2-with_curl: digest: sha256:53b5155746c81e992fd4437ad3174034cc3fb9b1c786667252be4054419ecc2a size: 1160
这样固化下来的镜像就推到了远程仓库