引言
Docker 是一种虚拟化技术的产品,属于一种 容器。容器是将软件打包成标准化单元,以用于开发、交付和部署。Docker镜像是用来启动容器的,也用来创建新的容器,类似于虚拟机的快照。
每个Docker镜像可以实例化出来多个容器
Docker的作用有很多,比如:提高开发效率、简化部署流程、降低运维成本等等。
为什么需要工程化?
采用工程化的方法来开发和管理Docker应用程序有很多好处。首先,Docker可以将应用程序打包成标准化单元,以用于开发、交付和部署,从而提高了开发效率 。其次,Docker可以简化部署流程,降低了运维成本 。此外,Docker还支持多平台、支持自动化部署、支持微服务架构等等 。
Docker镜像
打包Docker镜像需要Dockerfile,这是构建镜像的必需。
Dockerfile文件包含了构建镜像所需的指令和步骤。在Dockerfile中指定基础镜像、安装依赖项、复制应用程序文件等步骤,最后使用docker build命令来构建镜像。
示例:
bash
# 使用基础镜像
FROM node:14
# 设置工作目录
WORKDIR /usr/src/app
# 复制 package.json 和 package-lock.json 文件到工作目录
COPY package*.json ./
# 安装依赖项
RUN npm install
# 复制应用程序代码到工作目录
COPY . .
# 暴露端口号
EXPOSE 8080
# 启动应用程序
CMD [ "node", "app.js" ]
我们使用了Node.js作为基础镜像,并将应用程序代码复制到了容器中的/usr/src/app目录下。然后,我们使用npm install命令来安装应用程序的依赖项,并使用CMD指令来启动应用程序。最后,我们使用EXPOSE指令来暴露应用程序所使用的端口号
docker build -t myapp:latest .
来构建镜像。
其中,myapp是镜像的名称,latest是标签名,.表示Dockerfile所在的当前目录。
如何构建最小化镜像,避免包含不必要的文件
- 减少镜像层数:在Dockerfile中,一个RUN会在镜像上构建一层,因此需要将多个RUN合并执行,减少镜像层数。
- 移除不必要的文件:在Dockerfile中,可以使用COPY和ADD指令来复制应用程序代码和依赖项到容器中。在复制之前,需要先判断该文件是否是应用程序所必需的,如果是则复制到容器中,否则不复制。
- 使用多阶段构建:多阶段构建可以将构建过程分为多个阶段,每个阶段只编译应用程序所需的部分代码,从而减小最终镜像的大小。
Docker容器编排
Docker容器编排是指对Docker容器的配置和管理。
Docker Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组,定义和运行多容器的应用,可以一条命令启动多个容器 。我们开源的项目是基于docker-compose来进行管理的,主要优点是方便易用。
Docker Swarm是Kubernetes的前身之一,是Google开发的一个开源容器编排引擎。Swarm可以将多个Docker主机组成一个集群,对集群中的容器进行管理和编排。
Kubernetes是一个开源的容器编排平台,可以自动完成在部署、管理和扩展容器化应用过程中涉及的许多手动操作。它是Google 2014年创建管理的,是Google 10多年大规模容器管理技术Borg的开源版本 。
Kubernetes可以实现容器集群的自动化部署、自动扩缩容、维护等功能。它可以将运行Linux容器的多组主机聚集在一起,由Kubernetes帮助您轻松高效地管理这些集群。 Kubernetes集群可跨本地、公共云、私有云或混合云部署主机。因此,对于要求快速扩展的云原生应用而言(例如借助Apache Kafka进行的实时数据流处理),Kubernetes是理想的托管平台 。
容器网络配置
Docker容器网络配置有以下几种模式:
-
Bridge模式:这是默认的网络模式,它将容器连接到一个虚拟的bridge网络上,该网络由宿主机上的docker0桥接器创建。这种模式下,容器之间可以直接通信,但是无法访问外部网络。
-
Host模式:在这种模式下,容器共享宿主机的网络栈,可以使用宿主机的IP地址和端口号。这种模式下,容器可以直接访问外部网络。
-
Overlay模式:这种模式下,Docker使用Linux内核中的overlay协议来创建容器网络。这种模式下,容器之间的通信需要通过overlay网络进行,因此可以实现更高效的网络通信。
-
Macvlan模式:这种模式下,Docker使用Macvlan驱动程序来创建虚拟网卡,并将其绑定到指定的物理网卡上。这种模式下,容器可以直接访问外部网络。
-
None模式:这种模式下,容器没有自己的网络接口,也不能访问外部网络。如果需要访问外部网络,必须使用其他容器作为代理 。
我们开源项目目前的网络模式是bridge模式。预先新建一个docker网络。提供给compose内所有容器使用。在容器之间是可以直接通信的。
bash
docker network create --subnet=1.1.38.0/24 \
--ip-range=1.1.38.0/24 \
--gateway=1.1.38.254 \
docker_netaxe
在compose中,引入预先创建的docker网络,并配置external:true
external是Docker网络模式之一,它允许容器使用宿主机的网络堆栈,从而可以直接访问外部网络。在external模式下,Docker会为容器创建一个虚拟网卡,并将其绑定到宿主机的一个网络接口上。这样,容器就可以直接使用该网络接口来发送和接收数据包,从而实现与外部网络的通信。这并不是必须的。
存储管理
Docker卷 是Docker容器生产和使用持久化数据的首选机制。与绑定挂载相比,卷更容易备份或迁移。您可以使用Docker CLI命令或Docker API来管理卷。在Linux和Windows容器上都可以使用卷,而且可以更安全地在多个容器之间共享。 目前我们Kubernetes上的容器存储都是采用绑定数据挂载的。相比较单机而言,Kubernetes是集群部署的,数据挂载也是在专用的数据盘,会更安全更稳定。
要使用Docker卷或持久化存储来管理应用程序的数据,您需要执行以下步骤:
-
创建一个Docker卷。您可以使用
docker volume create
命令来创建一个新的卷。例如,要创建一个名为mydata
的卷,您可以运行以下命令:luadocker volume create mydata
-
将Docker卷挂载到容器中。您可以使用
-v
选项将卷挂载到容器中。例如,要将名为mydata
的卷挂载到名为/app/data
的目录中,您可以运行以下命令:javascriptdocker run -v mydata:/app/data myimage
-
在容器中访问数据。现在,您可以在容器中访问
/app/data
目录中的数据了。 -
或直接在docker-compose.yml文件中指定绑定卷
bash
volumes:
- ./victoriametrics:/victoriametrics
当前也可以定期备份数据、使用加密存储等手段。
日志和监控
使用Docker日志和监控工具来追踪应用程序的运行情况,并及时发现和解决问题。
基础用法
将容器内部的app日志映射到宿主机,排查故障时候可以直接在宿主机进行日志信息查询。
高级用法
将docker容器的日志打到日志组件,并在grafana或者kibana上进行日志可视化展示
docker容器可以配置日志驱动,--log-driver=logstash
或者--log-driver=loki
安全性考虑
Docker容器的安全性主要包括以下几个方面:
-
容器漏洞管理:选择信任的基础镜像,定期更新镜像以获取最新的安全补丁,避免使用未经验证的第三方镜像。借助安全扫描工具,对容器镜像进行漏洞扫描和分析,及时发现并修复潜在的安全风险 。
-
容器权限管理:确保容器运行所需的权限,避免不必要的权限开放。例如,如果您只需要读取某个目录下的文件,则不要将该目录设置为可写。
-
容器网络隔离:使用隔离网络来隔离容器之间的通信,避免恶意攻击者通过网络渗透到您的系统。
-
容器日志管理:记录容器的日志信息,并对其进行监控和分析。这有助于及时发现异常情况并采取相应措施。
-
容器安全扫描工具:使用容器安全扫描工具对容器进行全面扫描,及时发现并修复潜在的安全风险 。
限制容器访问
- 仅在容器中运行必要的服务,像ssh等服务绝对不能开启。
- Docker远程API访问控制,至少应该限制外网访问。
- 限制流量流向,使用iptables过滤器显示docker容器的源IP地址范围和外界通信。
- 使用普通用户启动Docker。
使用安全的镜像源
- 使用官方镜像源。
- 使用第三方镜像源时,应该选择可信的镜像源,并定期更新镜像以获取最新的安全补丁。
持续集成与交付(CI/CD)
Docker和CI/CD工具结合使用可以实现自动化的构建、测试和部署应用程序,提高开发效率和软件交付质量。以下是使用Docker进行CI/CD的一般步骤:
-
准备Docker镜像:在CI环境中,可以使用Docker镜像来构建和测试应用程序。首先,根据项目的要求选择合适的基础镜像,例如包含特定编程语言和工具的镜像。然后,编写Dockerfile文件,该文件定义了如何构建应用程序的容器。最后,使用docker build命令构建Docker镜像。
-
注册Runner服务器:为项目注册执行部署任务的Runner服务器。
-
提交更新,自动部署:提交代码到git master分支,等待Job任务完成。
-
测试结果:查看测试结果并进行必要的调整。
总结
本文介绍了在使用Docker进行应用程序开发和部署时采用一系列工程化的最佳实践。通过使用Dockerfile、多阶段构建、容器编排工具、持久化存储和健康检查等技术,可以确保应用程序的可靠性、可扩展性和可维护性 。
这些最佳实践包括:
- 使用Dockerfile来定义应用程序的构建过程。
- 使用多阶段构建来减小镜像大小并提高构建速度。
- 使用容器编排工具来管理容器集群。
- 使用持久化存储来保存数据,以便在容器重启后仍然可用。
- 使用健康检查来检测容器是否正常运行。
最后:检验真理最佳的途径是实践,鼓励大家在实践中不断尝试不断学习新的技术,来提高应用程序稳定和可靠性。