Docker工程化发展以及实践讲解

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
传统型负载均衡 CLB,每月750个小时 15LCU
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: Docker 是一种容器技术,可以让开发者在一个隔离的环境中运行和部署应用程序,从而提高应用程序的可移植性、安全性和效率。但是仅仅使用 Docker 并不能保证应用程序的可靠性、可扩展性和可维护性,为了实现这些目标,Docker 的使用也需要进行一些工程化改造。因此也就有了本文,本文中博主将给大家介绍 Docker 工程化的发展以及实践方式。

Docker 是一种容器技术,可以让开发者在一个隔离的环境中运行和部署应用程序,从而提高应用程序的可移植性、安全性和效率。但是仅仅使用 Docker 并不能保证应用程序的可靠性、可扩展性和可维护性,为了实现这些目标,Docker 的使用也需要进行一些工程化改造。因此也就有了本文,本文中博主将给大家介绍 Docker 工程化的发展以及实践方式。

Docker 工程化发展

Docker 工程化的发展历程可以追溯到 2013 年,当时 Docker 公司成立并推出了第一个版本以及 Dockerfile,Dockerfile 是一种文本文件,它包含了一系列的指令,用于定义一个 Docker 镜像。这些指令可以指定基础镜像、安装软件包、设置环境变量等等。通过 Dockerfile 开发者可以快速地构建自己的 Docker 镜像,从而实现快速部署和可移植性。

2015 年 Docker 推出 Docker Compose。Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。它使用一个 YAML 文件来配置应用程序的服务、网络和卷,然后使用一个命令来创建和启动所有服务。通过 Docker Compose 使得开发者可以更方便地管理和部署多容器应用程序

2017 年 Docker 推出 Docker Swarm 技术。Docker Swarm 是 Docker 自己的 Docker 容器本地集群解决方案,具有与 Docker 生态系统紧密集成并使用自己的 API 的优势。它监视跨服务器群集的容器数量,是在没有其他硬件的情况下创建群集 docker 应用程序的最便捷方式。

2023 年 Docker 发展至今 Kubernetes 已经成为了容器编排引擎的事实标准。Kubernetes 技术是在 2014 年正式发布的,是 Google 开源的一个容器编排引擎,用来对容器进行自动部署、扩缩和管理。本文会给大家简单介绍下 Kubernetes。

推荐博主开源的 H5 商城项目waynboot-mall,这是一套全部开源的微商城项目,包含三个项目:运营后台、H5 商城前台和服务端接口。实现了商城所需的首页展示、商品分类、商品详情、商品 sku、分词搜索、购物车、结算下单、支付宝/微信支付、收单评论以及完善的后台管理等一系列功能。 技术上基于最新得 Springboot3.0、jdk17,整合了 MySql、Redis、RabbitMQ、ElasticSearch 等常用中间件。分模块设计、简洁易维护,欢迎大家点个 star、关注博主。

github 地址:github.com/wayn111/way…

工程化实践

为了实现工程化目标,开发者需要遵循一些工程化的最佳实践,包括以下五个:

  • 使用 Dockerfile 来定义应用程序的镜像
  • 使用 docker-compose 来管理多个容器之间的依赖和协作
  • 使用 docker swarm 或 kubernetes 来实现容器的集群管理和服务发现
  • 使用 CI/CD 工具来自动化应用程序的构建、测试和部署
  • 使用监控和日志工具来收集和分析应用程序的运行状况和性能指标

使用 Dockerfile 来定义应用程序的镜像

Dockerfile 是一个文本文件,用来描述如何从一个基础镜像(例如 ubuntu 或 alpine)构建出一个新的镜像,包括安装依赖、复制文件、设置环境变量、暴露端口等操作。使用 Dockerfile 可以让开发者清晰地记录应用程序的配置和依赖,以及保证应用程序在不同的环境中运行的一致性。

一个简单的 Dockerfile 示例如下:

dockerfile

复制代码

# 基于 Java 镜像构建
FROM openjdk:8u212-jre
# 配置参数
ENV TZ=Asia/Shanghai
ENV JAVA_OPTS="-Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT+8 -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
# 设置时区
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 设置工作目录
WORKDIR /app
# 复制 jar 包到镜像里
COPY target/my-app.jar /app/my-app.jar
# 暴露端口
EXPOSE 8080
# 配置启动命令
CMD  java $JAVA_OPTS -jar /app/my-app.jar  --server.port=8080

简单介绍下上述 Dockerfile 示例的语法:

  1. FROM - 指定基础镜像,这里是基于开源的 Java 8 JRE 镜像。
  2. ENV - 设置环境变量,这里配置了时区、JVM 参数等。
  3. RUN - 执行命令,这里用来设置时区。
  4. WORKDIR - 设置工作目录,相当于 cd 命令,之后的命令都在这个目录执行。
  5. COPY - 复制文件到镜像,这里复制了编译好的 Java jar 包。
  6. EXPOSE - 声明暴露的端口,这里是 8080。
  7. CMD - 启动命令,这里配置了启动 Java 程序的命令。

我们要使用 Dockerfile 构建镜像的话,可以使用以下命令:

bash

复制代码

docker build -t my-app .

其中 -t参数指定了镜像的名称和标签(默认为 latest),.表示当前目录。

要运行构建好的镜像,可以使用以下命令:

bash

复制代码

docker run -p 8080:8080 my-app

其中 -p参数指定了容器内外部的端口映射关系,my-app是镜像的名称。

这样我们的 Java 服务就可以在容器里运行,并能够通过宿主机的 8080 端口访问了。

使用 docker-compose 来管理多个容器之间的依赖和协作

在实际开发中,一个应用程序通常不是单独运行的,而是需要与其他服务(例如数据库、缓存、消息队列等)进行交互。这些服务也可以使用 Docker 来运行,但是如果每个服务都需要单独使用docker run命令来启动,那么就会非常繁琐和容易出错。为了解决这个问题,可以使用 docker-compose 来定义和运行多个容器之间的依赖和协作关系。

docker-compose 是一个工具,可以让开发者使用一个 YAML 文件(通常命名为docker-compose.yml)来描述多个容器之间的配置,包括镜像、端口、环境变量、挂载卷、网络等。使用 docker-compose 可以让开发者一次性地启动或停止所有相关的容器,以及方便地管理容器之间的通信。

一个简单的 docker-compose.yml 示例如下:

yaml

复制代码

version: '3'
services:
  waynboot-mobile-api:
    image: ibm-semeru-runtimes:open-17-jdk
    container_name: mobile
    volumes:
      - /etc/localtime:/etc/localtime
      - /home/logs:/home/logs
      - /opt/waynboot-mall/upload:/opt/waynboot-mall/upload
      - ./jars/waynboot-mobile-api.jar:/home/app/waynboot-mobile-api.jar
    restart: always
    command: java -Xms512m -Xmx512m -Duser.timezone=GMT+8 -Dfile.encoding=utf-8 -jar /home/app/waynboot-mobile-api.jar
    ports:
      - "82:82"
    environment:
      - TZ=Asia/Shanghai
      - LOG_PATH_PREFIX=/home/logs
      - UPLOAD_DIR=/opt/waynboot-mall/upload
    network_mode: "host"
    # 依赖于redis和mysql,在启动本服务之前会先启动依赖的服务
    depends_on:
      - redis
      - mysql
      - rabbitmq
      - elasticsearch
  waynboot-admin-api:
    image: ibm-semeru-runtimes:open-17-jdk
    container_name: admin
    volumes:
      - /etc/localtime:/etc/localtime
      - /home/logs:/home/logs
      - /opt/waynboot-mall/upload:/opt/waynboot-mall/upload
      - ./jars/waynboot-admin-api.jar:/home/app/waynboot-admin-api.jar
    restart: always
    command: java -Xms512m -Xmx512m -Duser.timezone=GMT+8 -Dfile.encoding=utf-8 -jar /home/app/waynboot-admin-api.jar
    ports:
      - "81:81"
    environment:
      - TZ=Asia/Shanghai
      - LOG_PATH_PREFIX=/home/logs
      - UPLOAD_DIR=/opt/waynboot-mall/upload
    network_mode: "host"
    # 依赖于redis和mysql,在启动本服务之前会先启动依赖的服务
    depends_on:
      - redis
      - mysql
      - rabbitmq
      - elasticsearch
    # 依赖于redis和mysql,在启动本服务之前会先启动依赖的服务
    depends_on:
      - redis
      - mysql
      - rabbitmq
      - elasticsearch
  # Redis服务
  redis:
    container_name: redis
    image: redis:latest
    ports:
      - "6379:6379"
    volumes:
      - ./redis/redis.conf:/etc/redis/redis.conf
      - ./redis/data:/data
    command: redis-server /etc/redis/redis.conf
    network_mode: "host"
  # RabbitMQ
  rabbitmq:
    image: rabbitmq:management
    ports:
      - "5672:5672"
      - "15672:15672"
    container_name: rabbitmq
    environment:
      #rabbitmq的初始用户名
      RABBITMQ_DEFAULT_USER: guest
      #rabbitmq的初始密码
      RABBITMQ_DEFAULT_PASS: guest
    network_mode: "host"
  # MySQL服务
  mysql:
    container_name: mysql
    image: mysql:8.0.33
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: '123456'
      MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
      MYSQL_DATABASE: 'wayn_shop'
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./db-init:/docker-entrypoint-initdb.d
    command: mysqld --lower_case_table_names=1 --default-authentication-plugin=mysql_native_password
    network_mode: "host"
  # Elasticsearch服务
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.10.0
    container_name: elasticsearch
    volumes:
      - ./es/data:/usr/share/elasticsearch/data
      - ./es/plugins:/usr/share/elasticsearch/plugins
    environment:
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    network_mode: "host"
      -discovery.type=single-node      -bootstrap.memory_lock=true      -"ES_JAVA_OPTS=-Xms512m -Xmx512m"    network_mode:"host"

简单介绍下上述 docker-compose 示例语法:

  • version - 指定 docker-compose 版本,这里是 3。
  • services - 定义 compose 项目中的服务名称。
  • image - 指定服务使用的镜像。
  • container_name - 容器名称。
  • volumes - 数据卷挂载配置。
  • restart - 重启策略,这里是 always 表示总是重启。
  • command - 容器启动执行的命令。
  • ports - 映射宿主机和容器的端口。
  • environment - 设置环境变量。
  • network_mode - 网络模式,这里是 host 表示与宿主机共享网络命名空间。
  • depends_on - 声明服务依赖,确保在该服务启动前先启动依赖服务。

我们要使用 docker-compose 启动所有容器的话,可以使用以下命令:

bash

复制代码

docker-compose up -d

启动单个容器的话,可以使用以下命令:

bash

复制代码

docker-compose up waynboot-mobile

要停止所有的容器,可以使用以下命令:

bash

复制代码

docker-compose down

通过 docker-compose 我们就能够一键启动整个应用栈。

使用 docker swarm 或 kubernetes 来实现容器的集群管理和服务发现

docker swarm 和 kubernetes 都是用于管理容器化应用程序的集群化平台。它们可以实现以下功能:

  • 集群管理:将多个节点(物理机或虚拟机)组织成一个集群,提供统一的管理接口和调度策略。
  • 服务编排:将应用程序分解为多个微服务,定义服务之间的依赖关系和通信方式,实现服务的自动部署和更新。
  • 负载均衡:根据服务的访问量和性能,动态地分配请求到不同的节点或容器,实现服务的高可用性和弹性伸缩。
  • 服务发现:为服务分配唯一的标识和地址,实现服务之间的自动注册和发现,解决服务位置变化的问题。
  • 网络管理:为服务提供隔离和安全的网络环境,实现跨主机和跨区域的网络通信。
  • 存储管理:为服务提供持久化和共享的存储空间,实现数据的备份和恢复。

docker swarm 是 Docker 自带的集群管理工具,它使用 Docker 引擎作为节点间通信和状态同步的基础。docker swarm 可以直接使用 Docker 命令行工具和 API 进行操作,无需额外安装。docker swarm 支持使用 docker-compose.yml 文件来定义应用程序的服务,并使用docker stack deploy命令来部署应用程序到集群中。

kubernetes 是 Google 开源的集群管理平台,它使用 etcd 作为分布式键值存储来保存集群状态。kubernetes 需要在每个节点上安装 kubeadm、kubelet 和 kubectl 等组件,并使用 kubectl 命令行工具和 API 进行操作。kubernetes 支持使用 YAML 或 JSON 文件来定义应用程序的资源对象(如 Pod、Service、Deployment 等),并使用kubectl apply命令来部署应用程序到集群中。

docker swarm 和 kubernetes 的比较

docker swarm 和 kubernetes 有许多相同的功能,但每个工具在不同方面有自己的优势和劣势。下表提供了 docker swarm 和 kubernetes 在主要功能上的比较:

功能 docker swarm kubernetes
安装和配置 简单快速,无需额外安装 复杂繁琐,需要安装多个组件
命令行工具 使用 Docker CLI,与 Docker 容器操作一致 使用 kubectl,需要学习新的语法和概念
文件格式 使用 docker-compose.yml,与 Docker Compose 一致 使用 YAML 或 JSON,需要定义多种资源对象
集群状态 弱一致性,存在数据延迟 强一致性,实时同步
集群规模 适合小型或中型集群(最多几百个节点) 适合大型或超大型集群(最多数千个节点)
负载均衡 内置负载均衡器,自动将请求分发到容器 需要配置 Service 或 Ingress 对象,手动指定负载均衡策略
服务发现 使用内置 DNS 服务器,根据服务名称解析 IP 地址 使用内置 DNS 服务器,根据服务名称解析 IP 地址或端口号
网络管理 使用 overlay 网络,实现跨主机通信 支持多种网络插件,实现跨主机通信
存储管理 支持使用 volume 或 bind mount,实现数据持久化或共享 支持多种存储插件,实现数据持久化或共享
服务更新 支持滚动更新,可以指定更新批次和延迟 支持滚动更新,可以指定更新速率和策略
服务扩缩 支持手动或基于 CPU 利用率的自动扩缩 支持手动或基于多种指标的自动扩缩
服务监控 需要使用第三方工具,如 Prometheus 或 Grafana 需要使用第三方工具,如 Prometheus 或 Grafana
服务日志 需要使用第三方工具,如 ELK Stack 或 Fluentd 需要使用第三方工具,如 ELK Stack 或 Fluentd
社区支持 社区较小,活跃度较低 社区庞大,活跃度较高

本文关于 docker swarm 和 kubernetes 的介绍可能不够细致,欢迎各位评论留言补充。

使用 CI/CD 工具来自动化应用程序的构建、测试和部署

CI/CD 工具是指用于实现持续集成和持续部署的工具。持续集成是指将开发人员的代码频繁地合并到主分支,并进行自动化的构建和测试。持续部署是指将通过测试的代码自动化地部署到生产环境。

使用 CI/CD 工具可以带来以下好处:

  • 提高开发效率和质量,减少人为错误和冲突。
  • 加快交付速度和反馈周期,满足用户需求和市场变化。
  • 降低运维成本和风险,提高系统稳定性和安全性。

市面上有许多 CI/CD 工具可供选择,例如 Jenkins、GitLab CI、Travis CI、CircleCI、GitHub Actions 等。这些工具各有特点和优劣,需要根据项目的规模、技术栈、需求和预算等因素进行选择。

以 Docker 为例,使用 CI/CD 工具可以实现以下流程:

  • 开发人员在本地编写代码,并使用 Dockerfile 或 docker-compose.yml 来定义应用程序的镜像和服务。
  • 开发人员将代码推送到代码仓库(如 GitHub 或 GitLab),触发 CI/CD 工具的构建和测试流程。
  • CI/CD 工具使用 Docker 命令或 Docker GitHub Actions 等插件来构建镜像,并运行容器进行单元测试、集成测试、端到端测试等。
  • CI/CD 工具将通过测试的镜像推送到镜像仓库(如 Docker Hub 或私有仓库),并触发部署流程。
  • CI/CD 工具使用 SSH 或其他方式连接到目标服务器(如 Digital Ocean 或其他云服务商),并使用 Docker 命令或 docker-compose 命令来拉取镜像并运行容器。
  • CI/CD 工具返回部署结果,并发送通知或报告给开发人员或运维人员。

使用监控和日志工具来收集和分析应用程序的运行状况和性能指标

监控和日志工具是指用于收集、存储、展示和分析应用程序的运行状况和性能指标的工具。这些指标包括:

  • 容器的状态、资源利用率、事件等
  • 应用程序的响应时间、吞吐量、错误率等
  • 网络的延迟、流量、连接数等
  • 存储的容量、读写速度、IO 等

使用监控和日志工具可以带来以下好处:

  • 提高系统可见性和透明度,及时发现和定位问题。
  • 优化系统性能和资源分配,提升用户体验和满意度。
  • 支持系统决策和规划,预测系统需求和趋势。

市面上有许多监控和日志工具可供选择,例如 Prometheus、Grafana、ELK Stack、Fluentd 等。这些工具各有特点和优劣,需要根据项目的规模、技术栈、需求和预算等因素进行选择。

以 Docker 为例,使用监控和日志工具可以实现以下流程:

  • 在每个节点上安装并运行监控和日志代理(如 Prometheus Node Exporter 或 Fluentd),用于收集容器的指标和日志。
  • 在集群中部署并运行监控和日志服务器(如 Prometheus Server 或 Elasticsearch),用于存储和查询容器的指标和日志。
  • 在集群中部署并运行监控和日志可视化工具(如 Grafana 或 Kibana),用于展示和分析容器的指标和日志。
  • 在监控和日志可视化工具中配置仪表盘和图表,用于查看容器的状态、资源利用率、事件等。
  • 在监控和日志可视化工具中配置告警规则和通知方式,用于在容器出现异常或故障时发送通知或报告给开发人员或运维人员。

总结

工程化的 Docker 实践是构建可靠、安全、高效 Docker 应用的基石。遵循这些工程化思想可以大幅提升 Docker 应用部署运维的稳定性、效率和质量。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
3月前
|
Kubernetes Devops 持续交付
DevOps实践:使用Docker和Kubernetes实现持续集成和部署网络安全的守护盾:加密技术与安全意识的重要性
【8月更文挑战第27天】本文将引导读者理解并应用DevOps的核心理念,通过Docker和Kubernetes的实战案例,深入探讨如何在现代软件开发中实现自动化的持续集成和部署。文章不仅提供理论知识,还结合真实示例,旨在帮助开发者提升效率,优化工作流程。
|
1月前
|
Linux 持续交付 Docker
掌握Docker:从入门到实践
Docker 是一个开源容器引擎,允许开发者将应用及其依赖打包成可移植的容器,在任意 Linux 机器上运行。本文从基本概念入手,详细介绍 Docker 的安装、基本操作、镜像构建及 Docker Compose 的使用,并通过实战案例展示如何部署 Web 应用、构建微服务架构及实现 CI/CD。通过学习,你将掌握 Docker 的核心功能,提升应用开发和部署效率。
|
2月前
|
Linux iOS开发 Docker
Docker:容器化技术的领航者 —— 从基础到实践的全面解析
在云计算与微服务架构日益盛行的今天,Docker作为容器化技术的佼佼者,正引领着一场软件开发与部署的革命。它不仅极大地提升了应用部署的灵活性与效率,还为持续集成/持续部署(CI/CD)提供了强有力的支撑。
230 69
|
16天前
|
Kubernetes 持续交付 Docker
探索DevOps实践:利用Docker与Kubernetes实现微服务架构的自动化部署
【10月更文挑战第18天】探索DevOps实践:利用Docker与Kubernetes实现微服务架构的自动化部署
61 2
|
24天前
|
存储 运维 云计算
探索Docker容器化:从入门到实践
在这个快速发展的云计算时代,Docker容器化技术正在改变应用的开发、部署和管理方式。本文旨在为初学者提供一个关于Docker的全面入门指南,并通过实践案例展示Docker在实际开发中的应用。我们将一起了解Docker的核心概念、基本操作、网络和存储,以及如何构建和部署一个简单的Web应用。无论你是开发者还是运维人员,本文都会帮助你快速掌握Docker的核心技能。
|
25天前
|
运维 JavaScript 虚拟化
探索容器化技术:Docker的实践与应用
【10月更文挑战第9天】探索容器化技术:Docker的实践与应用
47 3
|
1月前
|
Ubuntu Linux 虚拟化
Docker入门实践(一)
Docker入门实践(一)
|
1月前
|
Kubernetes Cloud Native Docker
云原生时代的容器化实践:Docker与Kubernetes入门
【9月更文挑战第30天】在云计算的浪潮中,云原生技术正以前所未有的速度重塑着软件开发和运维领域。本文将通过深入浅出的方式,带你了解云原生的核心组件——Docker容器和Kubernetes集群,并探索它们如何助力现代应用的构建、部署和管理。从Docker的基本命令到Kubernetes的资源调度,我们将一起开启云原生技术的奇妙之旅。
|
20天前
|
运维 Kubernetes 监控
掌握Docker容器化技术:构建、部署与管理的高效实践
【10月更文挑战第14天】掌握Docker容器化技术:构建、部署与管理的高效实践
34 0
|
22天前
|
JavaScript 前端开发 Docker
拿下奇怪的前端报错(二):nvm不可用报错`GLIBC_2.27‘‘GLIBCXX_3.4.20‘not Found?+ 使用docker构建多个前端项目实践
本文介绍了在多版本Node.js环境中使用nvm进行版本管理和遇到的问题,以及通过Docker化构建流程来解决兼容性问题的方法。文中详细描述了构建Docker镜像、启动临时容器复制构建产物的具体步骤,有效解决了不同项目对Node.js版本的不同需求。