- bash 前台运行
- 容器持久运行的条件
- nginx 后台运行
- 后台运行的条件
- Docker数据存储的哲学
- Docker使用的哲学
前台运行容器
拉取 centos 镜像
1 | root@ubuntu:~# docker pull centos |
查看镜像列表
1 | root@ubuntu:~# docker images |
以前台运行方式运行容器
1 | root@ubuntu:~# docker run --name "mycentos" -it centos /bin/bash |
- run: 运行一个容器
- —name “mycentos”: 给容器命名
- -i: 打开容器的标准输入
- -t: 分配一个伪终端 tty
- centos: 镜像名
- 运行容器后执行的命令
语法:
1 | root@ubuntu:~# docker run --help |
操作容器
1 | yum install dstat htop lsof curl wget lrzsz |
退出终端/退出容器
1 | [root@e4b1ccd2600b /]# |
随着终端的退出, 容器也随之退出
容器持久运行的条件
阻塞!!!
Docker 容器持久运行的基本条件是-进程的阻塞!
Docker 的哲学中, 主张一个容器只启动”一个进程”, 这里的一个进程可以理解为一个程序 或是一个主进程, 比如一个 Apache, 一个 Apache 可以启动一个主进程和若干个子进程.
如果想让 Docker 持久化运行, 那么在容器启动时, 必须有一个进程阻塞住终端. Docker 判断容器内服务是否正常的方式很简单, 就是判断最后阻塞的进程是否挂掉, 如果最后阻塞的进程挂掉, 那么容器退出.
Docker 认为, 容器即服务, 容器即程序, 一个容器就是一个程序, 如果一个容器内启动了多个服务, 比如 A, B 和 C服务, C 作为最后一个程序阻塞住容器使其运行起来, 此时, 如果容器内部的 A 或 B 服务挂掉, 容器仍然认为自己是正常的, 因为 Docker 只关心最后阻塞的进程是否退出. 反之, A 和 B 服务正常, 如果 C 服务挂掉, 那么则整个容器退出!
后台运行容器
获取 nginx 镜像
右边是拉取 nginx latest 版本镜像的命令
左边 repo info 标签内是 nginx 简短说明/完整说明
完整说明中包括:
- 版本的介绍
- 软件的介绍
- 使用方式的介绍
左边 tag 是所有版本的列表
下载最新稳定发行版的 nginx 镜像
1 | root@ubuntu:~# docker pull nginx |
运行 nginx 镜像
1 | # 首先创建一个 web 目录 |
- -v: 挂载卷
宿主机目录:容器内目录:挂载方式
其中挂载方式支持以只读ro
或读写rw
方式挂载, 默认为rw
- -d: 以守护进程
daemon
方式放入到后台运行
此方式没有对外映射端口, 所以只能在容器内部访问
在容器内部访问页面
1 | # 进入容器 |
运行暴露端口的 nginx 镜像
1 | root@ubuntu:~# docker run --name "my-second-nginx" -v /root/web:/usr/share/nginx/html:ro -d -p 8800:80 nginx |
- -p: 对外映射端口
宿主机端口:容器内端口
运行暴露多个端口的 nginx 镜像
1 | root@ubuntu:~# docker run --name "my-third-nginx" -v /root/web:/usr/share/nginx/html:ro -d -p 8080:80 -p 443:443 nginx |
Docker 数据存储的哲学
Docker 主张运行无状态的容器, 什么样的容器是无状态的容器呢?
打个比方: 以上面的 nginx 实例为例
- 以如上方式
-v
挂载的方式即为有状态 - 以 dockerfile 的形式将数据目录预先拷贝到镜像的方式即为无状态
也可以简单的理解为:
- 镜像内包含数据且数据可随时随着镜像销毁的容器为无状态容器
- 镜像内只包含运行环境, 数据需要靠挂载目录的, 或是容器内数据不可随意销毁的容器为有状态容器
这两种用法各有利弊, 直至现在也争论不休, 没有最好的使用方式, 只有最合适的使用方式(注意: 在集群中, 最好使用无状态的方式. 但是最新版本的 k8s 已经支持有状态容器集群)
Docker 使用的哲学
由于 Docker 容器的生命周期完全取决于最后阻塞容器入口的进程的存活状态, 所以在使用容器的时候, 一定要多加注意阻塞入口的进程和主进程的关系. 比如 node.js 容器, 在里面使用pm2 管理的 node 项目, 最后阻塞入口的进程是 pm2, 那么里面 node 项目的管理就脱离了容器的控制, 而由 pm2 去接管, 在node 进程出问题时也是由pm2去控制重启的. 在实际使用情况中, 一定要注意这样的使用方式会不会对后续的维护造成不便. 我推荐使用原生的命令启动主进程, 不要在主进程外面再套一层程序管理层.