Docker容器
容器简介
Docker利用容器来开发、运行应用。 容器是镜像创建的实例。它可以被启动、开始、停止、删除。每个容器都是 相互隔离的、保证安全的平台。类似安装系统的电脑实体。简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环
境)和跑在上面的应用。
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
启动容器
启动容器有两种方式:
- 基于镜像新建一个容器并启动
- 将在终止状态(stopped)的容器重新启动。
新建启动容器
这里我们先操作基于镜像新建一个容器并启动
1 | #创建后台运行容器 |
-i
(input):打开容器的标准输入。-t
(terminal):告诉docker为容器建立一个命令行终端。-d
后台运行。--name
:指定容器名称,可以不填(随机),建议根据具体使用功能命名,便于管理。ubuntu
:告诉我们使用什么镜像来启动容器。/bin/bash
:告诉docker要在容器里面执行此命令。
将容器保存为镜像
查看容器id
1 | docker ps |
保存的格式:
1 | docker commit [选项] [容器ID或容器名] [仓库名:标签] |
例子:
1 | mac@sutune0223 ~ % docker commit -a 'sutune' -m 'add appium' 22fea2c5fd87 lf_client:v1.3 |
参数说明
-a
提交作者-m
提交修改点
启动已经存在的容器
首先我们使用命令docker ps -a
查询全部容器
1 | docker@default:~$ docker ps -a |
然后我们启动容器名称为sutune
的容器,从状态来看该容器暂时已经停止运行。使用命令docker start 容器id
即可启动已经存在的容器。
1 | docker@default:~$ docker start 300cbb2050a5 |
容器常用命令
创建容器
1.使用 docker create latest xxx
可以创建容器,ubuntu:latest
表示下载最新最新版本的镜像
1 | $ docker create ubuntu:latest |
创建交互型容器
运行在前台,容器中使用exit
命令或者调用docker stop
、docker kill
命令,容器停止。
1 | $ docker run -i -t --name=51zxw ubuntu /bin/bash |
参数说明
-i
(input):打开容器的标准输入。-t
(terminal):告诉docker为容器建立一个命令行终端。--name
:指定容器名称,可以不填(随机),建议根据具体使用功能命名,便于管理。ubuntu
:告诉我们使用什么镜像来启动容器。/bin/bash
:告诉docker要在容器里面执行此命令。
创建后台型容器
创建后与终端无关,只有调用docker stop
、docker kill
命令才能使容器停止。这里以我们创建nginx服务为例子。
1 | docker@default:~$ docker run -d --name webserver -p 80:80 nginx |
参数说明
-d
(deamon):后台守护模式运行-p
(port):映射端口,这里我们指定映射端口为80。
启动容器之后在浏览器输入对应的地址http://ip地址或localhost:80即可访问nginx主页。
- 如果是在 Linux 本机运行的 Docker,或者如果使用的是 Docker for Mac、Docker
for Windows,那么可以直接访问:http://localhost;- 如果使用的是 Docker Toolbox(记得不要填宿主机的ip而是toolbox客户端显示虚拟机ip),或者是在虚拟机、云服务器上安装的 Docker,则需要将 localhost 换为虚拟机地址或者实际云服务器地址。
还可以直接输入镜像ID 来启动容器。
1 | docker run -it -d --name huawei-nova4 b73c14a14a11 /bin/bash |
进入容器
docker exec
是需要容器处于运行中且进程也处于运行中才能执行的操作。命令执行后会进入容器的默认工作目录
1 | docker exec -it container_id /bin/bash |
-i
:即使没有附加也保持STDIN 打开-t
:分配一个伪终端
比如我们进入到运行ngnix
容器内部后,查看目录结构发现和一个独立的操作系统文件目录结构一样。
1 |
|
如果需要退出容器,则执行exit
即可
如果我们想修改上面nginx服务的默认页面,我们可以进入到webserver
容器进行修改。
1 | docker@default:~$ docker exec -it webserver /bin/bash |
执行之后刷新页面,我们可以看到nginx首页变成了我们自定义的页面内容。
查看容器列表
1.使用 docker container ls -all
来查看所有的容器,如果查看正在运行的就不需要加参数 --all
1 | $ docker container ls --all |
2.使用 docker ps -a
查看,如果需要查看正在运行的容器就不用加-a
参数
重启容器
使用 docker restart
来重启正在运行的容器。
1 | $ docker restart 5e644f959f0b |
容器自动重启
Docker提供了
restart policy
机制,可以在容器退出或者Docker重启时控制容器能够自启动。这种Restart policy
可以保证相关容器按照正确顺序启动。虽然也可以通过进程监控的方式(如systemd
)来完成这种动作,但Docker还是建议尽量避免使用进程监控的方式来 “自启动” 容器。Docker的
Restart policy
与dockerd
命令的--live-restore
启动标志还有区别:--live-restore
标志可以在Docker升级的时候保证容器继续运行,但是网络以及用户终端输入会被中断。
那到底什么是restart policy
呢?我们来看看实际的情况吧。
restart policy
restart policy在使用docker run启动容器时通过--restart
标志指定,这个标志有多个value
可选,不同的value
有不同的行为,如下表所列:
值|描述
—|—
no|不自动重启容器. (默认value)
on-failure| 容器发生error而退出(容器退出状态不为0)重启容器
unless-stopped| 在容器已经stop掉或Docker stoped/restarted的时候才重启容器
always |在容器已经stop掉或Docker stoped/restarted的时候才重启容器
restart policy细节
- 容器只有在成功启动后
restart policy
才能生效。这里的”成功启动”是指容器处于up
至少10秒且已经处于docker监管。这是避免没有成功启动的容器陷入restart
的死循环。 - 如果手动(
manually
)的stop
(与前面的explicitly stopped
有何区别)一个容器,容器设置的restart policy
将会被忽略,除Docker daemon
重启或者容器手动重启。这是避免了另外一种死循环。 estart policies
只能用于容器,对于swarm services
其restart policies
有不通过的配置。
停止容器运行
使用 docker stop
来停止正在运行的容器
1 | Shuqing@LAPTOP-8B5JADC8 MINGW64 /d/Program Files/Docker Toolbox |
停止全部容器运行
1 | docker rm $(docker ps -a -q) |
删除容器
1.使用 docker rm
删除已经停止的容器
1 | $ docker rm 92d1b548ad88 |
2.使用 docker rm -f
删除正在运行的容器
1 | $ docker rm -f 5e644f959f0b |
Tips:可以删除多个容器 docker rm container1 container2
3.删除全部容器
1 | docker rm $(docker ps -a -q) |
查看容器log
1 |
|
查看容器详细信息
使用docker inspect
可以查看容器的详细配置信息
1 | docker@default:~$ docker inspect hello-world |
踩坑相关
容器内部无法连接外部网络
方法1
查询docker网络的转发原理,docker中的网络是通过NAT转发至宿主主机处理的,遂查询宿主主机防火墙NAT转发情况:
1 | firewall-cmd --query-masquerade |
通过以上情况可见在此宿主主机中防火墙的NAT转发并未开启,通过以下命令开启,并重启防火墙:
1 | firewall-cmd --zone=public --add-masquerade --permanent |
方法2
把docker0网卡添加到trusted域
1 | firewall-cmd --permanent --zone=trusted --change-interface=docker0 |
然后关闭所有容器
1 | docker stop $(docker ps -aq) |
重启docker服务
1 | systemctl restart docker.service |