你遇到的问题,可能比你解决的问题还多。。。
目前docker 镜像,没有统一标准,体现在一下几个方面。
即使是镜像采用 CentOS 母版,很多镜像制作者会给操作系统减肥。经过优化后,已经不是官方版本,在使用过程中你会遇到各种麻烦。例如调试的时候需要 curl,wget,telnet,nslookup 等工具在镜像中没有。甚至 ps, top, free, find, netstat, ifconfig 命令都没有。
很多容器都不带 iptables 所以,即使带有iptables 在容器中修改规则也很麻烦。
传统OS 以 CentOS为例,有严格的安装规范,例如:
通常安装位置是: /etc/example 配置文件 /bin/sbin 二进制文件 /var/lib/example 数据文件 /var/log/example 日志文件 /var/run/example PID 文件 /etc/sysconfig/example 启动参数文件 /etc/system.d/example 启动脚本
或者被安装在: /usr/local/etc 配置文件 /usr/local/bin 可执行文件 /usr/local/share 文档
最后一种是独立安装在: /usr/local/example 下
容器镜像那可是五花八门,没有统一标准,如果不看 Dockerfile 根本不知道作者将文件安装到了哪里。
常常存储目录被放置在根目录。例如 /data
Linux 系统也存在BUG,在我的20年执业生涯中是遇到过 Linux 系统有BUG的,还向 Redhat 提交过 BUG。如果你采用的镜像有BUG,你想过怎么去debug 吗?
程序启动的区别
在Linux是一般是采用守护进程方式启动。启动后进入后台,启动采用 systemd
容器中启动通常是直接运行,这样的运行方式,相当于你在linux的Shell 终端直接运行一样,是在前台运行,随时 CTRL + C 或者关闭终端窗口,程序就会退出。容器采用这种方式启动,就是为了让 docker 管理容器,docker 能够感知到容器的当前状态,如果程序退出,docker 将会重新启动这个容器。
守护进程方式需要记录 pid 即父进程ID,用于后面管理该进程,例如可以实现 HUP 信号处理。也就是 reload 操作,不用退出当前程序实现配置文件刷新。处理 HUP 信号,无需关闭 Socker 端口,也不会关闭线程或进程,用户体验更好。
容器是直接运行(前台运行),所以没有 PID 也不能实现 reload 操作。 配置文件更新需要重新启动容器,容器启动瞬间TCP Socker 端口关闭,此时用户会 timeout。甚至该服务可能会引起集群系统的雪崩效应。
很多镜像制作者更趋向使用环境变量传递启动参数。
当然你也可以在容器中使用 systemd ,这样做容器不能直接感知到容器的运行状态,systemctl stop example 后,容器仍然正常。需要做存活和健康检查。通过健康状态判断容器的工作情况。如果处于非健康状态,将该节点从负载均衡节点池中将它踢出去。
Linux 启动一个应用远远比docker 启动一个容器速度要快。因为物理机或者虚拟机的Linux操作系统已经启动,虚拟机也分配了资源,运行可执行文件基本上是瞬间启动。而 docker 启动容器,要分配资源(分配内存和CPU资源,新建文件系统),相当于创建一个虚拟机的过程,最后载入约200MB左右的镜像,并将镜像运行起来,所以启动所需时间较长,有时不可控,尤其是Java应用更为突出。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。