docker 容器
- 什么是容器?
- 容器的生命周期
- 容器命令
-
- [docker create](#docker create)
- [docker start](#docker start)
- [docker run](#docker run)
- [docker ps](#docker ps)
- [docker stats](#docker stats)
- [docker logs](#docker logs)
- [docker attach](#docker attach)
- [docker stop](#docker stop)
- [docker exec](#docker exec)
- [docker restart](#docker restart)
- [docker kill](#docker kill)
- [docker top](#docker top)
- [docker container inspect](#docker container inspect)
- [docker port](#docker port)
- [docker cp](#docker cp)
- [docker diff](#docker diff)
- [docker commit](#docker commit)
- [docker pause](#docker pause)
- [docker unpause](#docker unpause)
- [docker rm](#docker rm)
- [docker export](#docker export)
- [docker wait](#docker wait)
- [docker rename](#docker rename)
- [docker container prune](#docker container prune)
- [docker update](#docker update)
- 容器操作案例
- 综合实战
-
- MySQL容器化安装
- redis容器化安装
- [C++ 容器制作](#C++ 容器制作)
- 常见问题:
什么是容器?
通俗地讲,容器是镜像的运行实体。镜像是静态的只读文件,而容器带有运行时需要
的可写文件层,并且容器中的进程属于运行状态。即容器运行着真正的应用进程。容器有初建、运行、停止、暂停和删除五种状态。虽然容器的本质是主机上运行的一个进程,但是容器有自己独立的命名空间隔离和资源限制。也就是说,在容器内部,无法看到主机上的进程、环境变量、网络等信息,这是容器与直接运行在主机上进程的本质区别。容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。 这将添加一个容器层,该层允许修改镜像的整个副本。
容器的生命周期
容器的生命周期是容器可能处于的状态:
created:初建状态
running: 运行状态
stopped:停止状态
paused:暂停状态
deleted:删除状态
各个生命周期转换图如下:
下面我们将结合小汽车启动的例子来讲解这几个状态;
- docker create :创建容器,此时容器处于created状态,不会进入running状态;在小汽车例子中类似于我们插入钥匙,点火,但是小汽车并没有跑起来;
- docker run: 创建容器,并立即启动容器,此时容器处于running状态;在小汽车例子中,类似于我们插入钥匙,点火,然后发动发动机,让小汽车跑起来;
- docker start: 让容器运行起来(前提是容器已经存在);
- docker stop: 将容器停止起来;在小汽车例子中类似于熄火;
- docker kill: 容器在故障(死机)时,执行 kill(断电),容器转入停止状态,这种操作容易丢失数据,除非必要,否则不建议使用;
- docker restart: 重启容器,容器转入运行状态;
- docker pause: 容器进入暂停状态,类似于小汽车在运行中,突然踩了一脚刹车,并没有熄火;
- docker unpause: 取消暂停状态,容器进入运行状态;
- docker rm : 删除容器
- killed by out-of-memory(因内存不足被终止) :宿主机内存被耗尽,也被称为 OOM:非计划终止 这时需要杀死最吃内存的容器
- container process exitde(异常终止):出现容器被终止后,将进入 Should restart?选
择操作:yes 需要重启,容器执行 start 命令,转为运行状态。
no 不需要重启,容器转为停止状态。
容器OOM:Docker 在处理 OOM 事件时分为三种情况:
- 如果容器中的应用耗尽了主机系统分配给容器的内存限额,就会触发 OOM 事件。例如,在容器当中,部署了一个 web 服务。假设主机分配给此容器的内存上限为 1G,当脚本申请的内存大于 1G 时,此容器就会触发 OOM 事件。而在这种情况下,此容器将会被强制关闭。但需要注意的是,此时关闭容器的并非是 Docker Daemon,而是宿主机操作系统。因为一个容器其实就是一组运行在宿主机操作系统当中的进程,宿主机操作系统通过cgroups 对这组进程设定资源上限,当这些进程申请的资源到达上限时,触发的是宿主机操作系统的内核 OOM 事件,因此最终是由宿主机内核来关闭这些进程.
- 如果用户不想关闭这个容器,那么可以选择--oom-kill-disable 来禁用 OOM-Killer。使用此参数时,仍需要注意,如果使用-m 设置了此容器内存上限,那么当容器到达内存资源上限时,主机不会关闭容器,但也不会继续向此容器继续分配资源,此时容器将处于 hung 状态。只需要将最坏的情况封闭在一定范围之内,而不至于蔓延出去。
- 如果用户使用了--oom-kill-disable,但也没有使用-m 来设定上限,因而此时此容器将会尽可能多地使用主机内存资源。换言之,主机内存有多大,它就将用多大。
容器异常退出 :每个容器内部都存在一个 Init 进程,容器中其他所有进程都是此进程的子进程。运行的容器是因为 Init 进程在运行,如果一个子进程因为某种原因造成了退出,那么其父进程也会同步退出,直至 Init 进程也退出。当 Init 进程退出时,也就代表着此容器被关闭。ocker 目前没有办法知道此时的进程退出属于正常退出还是异常退出。当出现容器关闭情况时,Docker Daemon 会尝试再次重新将此容器由 Stopped 状态转为 Running状态。只有设置了--restart 参数的容器,Docker Daemon 才会去尝试启动,否则容器会保持停止状态。
容器暂停 :Docker"剥夺"了此容器的 CPU 资源。而其他资源,如 Memory 资源、Network 资源等还保留未动。如此一来,失去了 CPU 资源的进程,是不会被主机内核系统所调度的,所以此容器就处于"冰封"状态。
容器命令
docker create
语法 :docker container create [options] image [command] [arg...]
别名 :docker create
功能 :基于某个镜像,创建出一个容器,但是并不会启动容器,此时容器处于created状态;
参数 :
command: 容器启动要执行的命令
-- restart: 在容器退出时,自动重启;
其余参数,大多与docker run一致,可以参考docker run的参数;
注意docker create 没有-d选项!!!
实战 :
docker start
语法 :docker container start [options] container [container...]
别名 :docker start
功能 :启动一个或多个停止的容器;
参数 :
-i: 以交互的方式启动容器;
-a: 前台方式启动容器,将容器的日志信息,打印到标准输出,标准错误;
实战 :
docker run
详细请看这篇博客:
docker run
docker ps
详细请看这篇博客:
docker ps
docker stats
docker logs
语法 :docker container logs [options] container
别名 :docker logs
功能 :获取容器的日志信息;
参数 :
--details: 显示详细的日志信息
-f: 实时追踪日志消息
--tail N: 从末尾开始显示N条日志消息;
--since: 显示自xxx时间以来的日志信息
-t: 显示时间戳
实战 :
docker attach
语法 :docker container attach
别名 :docker attach
功能:将本地标准输出、标准输入、标准错误附加到容器上;这里附加的意思,可以理解为绑定,例如:标准输出附加的意思就是:"容器内部产生的输出(例如,应用程序的打印语句)将会被发送到宿主机的终端或指定的文件/设备。这样,用户就可以在宿主机上查看容器的输出信息。"其它也是同理;
参数 :
--sig-proxy:是否将所有信号代理,默认是 true,如果设置为 false,退出的 话不会影响容器,否则退出会导致容器退出。
实战 :
docker stop
语法 :docker container stop [OPTIONS] CONTAINER [CONTAINER...]
别名 :docker stop
功能 :容器内的主进程将接收SIGTERM,并在宽限期后接收SIGKILL。第一个信号可以用容器的Dockerfile中的STOPSIGNAL指令来改变,或者用--stop-signal选项来改变docker运行。
参数 :
-t: 在杀死容器之前需要停止几秒
-s: 停止容器用的信号
实战 :
docker exec
语法 :docker container exec [OPTIONS] CONTAINER COMMAND [ARG...]
别名 :docker exec
功能 :在一个运行的容器中执行命令
参数 :
-d: 以后台的方式来运行命令;
-i:以交互的方式运行命令,保持stdin打开
-t: 分配一个伪终端
-w: 指定命令执行的工作目录
-e: 设置环境变量
-u: 以指定用户来运行
实战 :
docker restart
语法 :docker container restart [options] CONTAINER [CONTAINER...]
别名 :docker restart
功能 :重新启动一个或多个容器;
实战 :
docker kill
语法 :docker container kill [options] CONTAINER [CONTAINER...]
别名 :docker kill
功能 :杀死一个或多个正在运行的容器;
实战 :
注意: dokcer kill 与docker stop都是停止容器,但是docker kill更加暴力,有可能会造成数据丢失,而docker stop比较温和,在真正终止容器之前,会先停留一段时间,让容器完成一些"停止前的工作";
docker top
语法 :docker container top CONTAINER [ps options]
别名 :docker top
功能 :查看一个运行的容器中的进程信息;[ps options]这里表示参数支持ps命令的参数,在写的时候不需要带上ps,直接写它的参数即可;
实战 :
docker container inspect
语法 :docker container inspect [options] CONTAINER [CONTAINER...]
功能 :查看一个或多个容器的详细信息
参数 :
-f: 返回指定值的模板文件
-s:显示总的大小
注意:
docker inspect 会自动检查是容器还是镜像来显示信息;
实战 :
docker port
语法 :docker container port CONTAINER [PRIVATE_PORT[/PROTO]]
别名 :docker port
功能 :查看容器的端口映射情况或者使用 [PRIVATE_PORT[/PROTO]] 查看指定端口在宿主机上的映射情况
实战 :
docker cp
语法 :docker container cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
别名 :docker cp
功能 :在宿主机和容器之间拷贝文件
实战 :
docker diff
语法 :docker container diff CONTAINER
别名 :docker diff
功能 :检查对容器文件系统上的文件或目录的更改
解释 :
A: 一个新文件或目录被添加;
D: 一个新文件或目录被删除;
C: 一个新文件或目录被改变;
实战 :
docker commit
语法 :docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
别名 :docker commit
功能 :根据容器的改变创建一个新的镜像;
参数 :
-a: 指定镜像作者
-m: 镜像介绍信息;
-c:将dockerfile指令应用于创建的镜像;
-p: 提交期间暂停容器,默认为true,如果不想暂停可以设置为false;
实战 :
docker pause
语法 :docker container pause CONTAINER [CONTAINER...]
别名 :docker pause
功能 :暂停一个或多个容器里面的所有进程
实战 :
docker unpause
语法 :docker container unpause CONTAINER [CONTAINER...]
别名 :docker unpause
功能 :取消暂停一个或多个容器内的所有进程
实战 :
docker rm
docker export
语法 :docker container export [OPTIONS] CONTAINER
别名 :docker export
功能 :将容器的文件系统导出为tar包
参数 :
-o:输出文件,默认stdout
实战 :
解包的命令是:docker image import / docker import
docker import exportTest.tar exporttest:v1
docker save 和docker export都可以压缩成镜像包,那么一般选择那个比较好?
答:一般选择docker save比较多一点,因为docker export导出来的镜像会有部分元数据丢失:
但是docker save导出来的镜像包是基于镜像的,而docker export是基于容器导出来的,因此容器中做出的修改操作,也会被导出来;
docker wait
语法 :docker container wait CONTAINER [CONTAINER...]
别名 :docker wait
功能 :阻塞等待直到一个或多个容器停止,然后打印它们的退出代码
实战 :
docker rename
语法 :docker container rename CONTAINER NEW_NAME
别名 :docker rename
功能 :给容器重命名
实战 :
docker container prune
语法 :docker container prune [OPTIONS]
功能 :删除所有停止的容器
参数 :
-f: 不提示确认信息
实战 :
docker update
语法 :docker container update [OPTIONS] CONTAINER [CONTAINER...]
别名 :docker update
功能 :更新一个或多个容器的配置信息
参数 :
--cpus:cpu 数量
--cpuset-cpus :使用哪些 cpu
--memory :内存限制 ○ --memory-swap:交换内存
--cpu-period :是用来指定容器对 CPU 的使用要在多长时间内做一次重新分配
--cpu-quota:是用来指定在这个周期内,最多可以有多少时间用来跑这个容器
实战 :
容器操作案例
容器基本操作
- 通过nginx镜像文件创建容器:
- 查看容器信息
- 停止当前容器
- 删除容器
容器的状态转移
- 创建容器:
- 通过docker ps -a我们查看到容器的状态为created:
- 通过docker start启动容器;
- 通过docker ps -a查看容器状态:
- 通过docker stop停止容器:
- 重新启动容器,然后使用docker kill杀掉容器:
- docker rm -f 强制删除正在运行的容器:
容器交互模式
attached模式
docker container run -p 80:80 nginx
- 通过上述方式创建容器,就是 attached 模式,这样容器会在前台运行
- 访问服务器网址的时候,每访问一次,命令窗口就会打印一次日志,Docker 容器的日志会实时的展现到窗口并且占用此端口
- 如果是在 Linux 服务器上,按 Ctrl+C 就会停止掉 Docker 服务,很容易误操作,所以我们需要一个更好的,更稳定的模式,对应的是 detached 模式
- attached 模式仅适用于容器和程序的调试阶段
detached 模式在 docker container run -p 80:80 nginx 命令基础上加一个-d 或者--detach选项表示 detached 模式, 即在后台执行
- 在后台运行,启动后只显示容器 ID,并且可以输入任何命令
- 就算关掉窗口依然继续运行,停止和删除容器都需要使用 shell 命令,减少了很多
的误操作- 比起 attached 模式更建议使用
interactive 模式当我们创建好一个容器之后, 可能需要去容器内部获取一些信息或执行一些命令,就需要进入到交互式模式。例如创建一个 Ubuntu 容器之后,需要到系统里输入各种Shell 命令和系统进行交互就需要进入交互式模式才可以完成.
- 创建运行容器并进入到交互模式
docker container run -it nginx:1-perl bash
- 退出交互式模式: 在交互式 shell 中输入 exit
宿主机与容器内容拷贝
- 将容器内的index.html文件拷贝到宿主机:
- 修改index.html目录中的内容,并拷贝会容器中
- 我们来请求一下nginx服务:
发现nginx的默认界面发生变化,说明本次实验成功!
容器自动删除
- 在docker run启动容器的时候,带上--rm 选项:
- docker stop停止容器,并查看容器信息:
容器自动重启
容器重启选项如下:
docker run --restart=no [容器名] :默认值不自动重启
docker run --restart=on-failure:3 [容器名] : on-failure 若容器的退出状态非 0,则
docker 自动重启容器,还可以指定重启次数,若超过指定次数未能启动容器则放弃
docker run --restart=always [容器名] :always 容器退出时总是重启
docker run --restart=unless-stopped [容器名] unless-stopped 容器退出时总是重启,
但不考虑 Docker 守护进程启动时就已经停止的容器
如果容器启动时没有设置--restart 参数,则通过下面命令进行更新:
docker update --restart=always [容器名]
- 使用docker run启动容器,并且开启自动重启:
- 进入容器内部,杀掉1号进程,模拟程序崩溃:
容器日志查看
- 运行一个容器
使用docker logs命令查看日志:
也可以直接去docker root目录下查看:
进入containers目录:
根据要查看的容器的容器id进入对应目录:
查看"容器id-json.log" 文件
通过这样的办法,我们也可以查看容器日志信息;
综合实战
MySQL容器化安装
- 进入dockerHub选取MySQL镜像:
- 我们选取最新镜像吧:
- 查看一下镜像的详细信息:
- 启动mysql镜像:
- 进入容器:
- 进入mysql服务,并建一张表,在表中写入数据:
- Windows客户端远程连接mysql服务:
redis容器化安装
- 查看redis镜像:
- 拉取所有rediis镜像
- 查看redis镜像详细信息:
- 启动redis镜像服务:
- 进入容器内的redis服务:
- 通过其它redis客户端链接到redis容器:
C++ 容器制作
- 下载centos镜像:
- 启动容器
- 将yum源换为国内源(参看中科大源网站)
参考这篇博客CentOS 8 安装国内、本地YUM源- 下载g++ 和vim
yum groupinstall "Development Tools"
yum -y install vim
- 编写C++代码:
- 编译代码:
- 在容器中运行:
- 退出容器:
- docker start 启动容器:
常见问题:
docker import 和 docker load 有什么区别?
- docker save images_name:将一个镜像导出为文件,再使用 docker load 命令将文件导入为一个镜像,会保存该镜像的的所有历史记录。比 docker export 命令导出的文件大,很好理解,因为会保存镜像的所有历史记录。
- docker export container_id:将一个容器导出为文件,再使用 dockerimport 命令将容器导入成为一个新的镜像,但是相比 docker save 命令,容器文件会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。既可以使用 docker load 命令来导入镜像库存储文件到本地镜像库,也可以使用docker import 命令来导入一个容器快照到本地镜像库
- 两者的区别在于容器快照将会丢弃所有的历史记录和元数据信息,而镜像存储文件将保存完整记录,体积也会更大