Docekrfile和docker compose编写指南及注意事项
Dockerfile
基础语法
我们通过编写dockerfile,将每一层要做的事情使用语法固定下来,之后运行指令就可以通过docker来制作自己的镜像了。
构建镜像的指令:docker build /path -t imageName:tag
注意,docker build后的path必须是dockerfile文件所在的目录。
制作镜像的过程中的输出信息挺详细的,如果我们编写的dockerfile文件有误,可以直接通过输出判断,并对dockerfile文件进行更改。
指令 | 说明 | 示例 |
---|---|---|
FROM | 指定基础镜像 |
|
ENV | 设置环境变量,可在后面指令使用 |
|
COPY | 拷贝本地文件到镜像的指定目录 |
|
RUN | 执行Linux的shell命令,一般是安装过程的命令 |
|
EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT java -jar xx.jar |
dockerfile编写模板
Go程序Dockerfile模板【两阶段构建】
# 构建:使用golang:1.21版本
FROM golang:1.21 as build# 容器环境变量添加 容器内部的环境变量 key value的形式
ENV GO111MODULE=on \GOPROXY=https://goproxy.cn,direct \CGO_ENABLED=0 \GOOS=linux \GOARCH=amd64#移动到工作目录,没有该目录会自动创建
WORKDIR /go/release# 把全部文件复制到/go/release目录
COPY . .# 编译: 把main.go编译为可执行的二进制文件, 并命名为app
RUN go build -o dijiexiaApp# 运行: 使用scratch作为基础镜像
FROM alpine as prod# 在build阶段, 复制时区配置到镜像的/etc/localtime
COPY --from=build /usr/share/zoneinfo/Asia/Shanghai /etc/localtime# 在build阶段, 复制./app目录下的可执行二进制文件到当前目录
COPY --from=build /go/release/dijiexiaApp /# 在build阶段, 复制yaml配置文件到当前目录, 此处需要注意调用该配置文件时使用的相对路径, main.go在当前目录下执行
# 一些配置文件不需要在容器内部进行创建,回来直接挂载到容器外部即可,
COPY --from=build /go/release/conf /conf
COPY --from=build /go/release/app/casbin/model.conf /app/casbin/EXPOSE 8000
EXPOSE 8001# 启动服务 CMD是运行镜像时,执行的命令
ENTRYPOINT ["./dijiexiaApp","./conf/develop.yaml"]
Java程序Dockerfile模板
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
ENV TZ=Asia/Shanghai
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 设定时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装JDK
RUN cd $JAVA_DIR \&& tar -xf ./jdk8.tar.gz \&& mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 指定项目监听的端口
EXPOSE 8080
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
docker compose
一般我们的项目通常包含多个容器,比如业务项目容器、MySQL容器、Redis容器、RabbitMQ容器。如果我们仍然采用手动部署的方式,是比较麻烦的。我们需要逐个将容器启动,并且需要记录容器的启动顺序,因为容器之间可能存在依赖的关系。复杂一点的话,我们还需要将各个容器加入到一个网络中,方便通过容器名进行通信。而通过Docker Compose可以帮助我们实现多个相互关联容器的快速部署。
docekr-compose.yaml文件的编写语法大致和通过命令启动容器的格式一致,以下是它们之间的关系
docker run 参数 | docker compose 指令 | 说明 |
---|---|---|
--name | container_name | 容器名称 |
-p | ports | 端口映射 |
-e | environment | 环境变量 |
-v | volumes | 数据卷配置 |
--network | networks | 网络 |
docker-compose编写模板
version: "1.1"services:mysql:image: mysqlcontainer_name: diJieXiaMysqlports:- "3710:3306"environment:TZ: Asia/ShanghaiMYSQL_ROOT_PASSWORD: 123volumes:- /opt/dijiexia_mysql/conf:/etc/mysql/conf.d #目录挂载MySQL的配置文件- /opt/dijiexia_mysql/data:/var/lib/mysql #目录挂载MySQL的数据- /opt/dijiexia_mysql/init:/docker-entrypoint-initdb.d #初始化数据库脚本挂载点,MySQL容器首次启动时,会自动执行.sh,.sql文件networks:- diJieXiaredis:image: rediscontainer_name: diJieXiaRedisports:- "3711:6379"command: ["redis-server", "--requirepass", "123456"]networks:- diJieXia#通过重新构建镜像的方式获取Go镜像,相当于docker build .dijiexia:build:context: .dockerfile: Dockerfilecontainer_name: diJieXiaProjectports:- "8001:8001"- "8000:8000"networks:- diJieXiadepends_on:- mysql- redisnginx:image: nginxcontainer_name: diJieXiaNginxports:- "3712:80"volumes:- /opt/dijiexia_front/nginx/conf/nginx.conf:/etc/nginx/nginx.conf #将nginx的配置文件nginx.conf挂载出来- /opt/dijiexia_front/nginx/conf.d:/etc/nginx/conf.d #挂载nginx的配置文件夹,通过在nginx.conf中的设置,会自动读取给目录下以.conf结尾的文件- /opt/dijiexia_front/nginx/html:/usr/share/nginx/html #将加载静态页面的目录挂载出来networks:- diJieXia
networks:diJieXia:name: diJieXia111
简单的depends_on存在的问题:
在本版本的docker-compose.yaml文件的模板中,会有一个问题:我们的Go程序会启动失败,原因是因为Go程序所依赖的MySQL容器和Redis容器没有完全启动成功,导致Go程序获取MySQL或Redis连接的时候失败。
虽然在yaml中,我们在yaml文件中设置了depends_on,让MySQL容器、Redis容器先于GO业务程序启动。但是可能存在我们的MySQL容器和Redis容器还未启动完毕,而我们的Go程序已经启动了,从而导致我们的Go程序启动失败。理想情况下是MySQL和Redis容器启动完毕并且保证可用后,我们的Go程序才开始启动。因此,在启动Go程序之前,需要对MySQL和Redis做健康检查,确保MySQL和Redis已经启动成功了。如果MySQL或Redis启动失败了,我们还需要将启动失败的容器进行重启或者选择忽略。
为此,DockerCompose提供了两种机制
condition说明:
为此,Docker中提供了一种长定义的模式,方便我们对容器编排的过程做更加精准的设置。
- condition: service_started
- condition: service_healthy
- condition: service_completed_successfully
如果condition设置为service_started,只表示在该容器在所有依赖服务后启动,不保证依赖容器的可用性。
如果condition设置为service_healthy,表示等待依赖服务的健康状态后在启动相关服务。其中健康状态通常是在同期中运行健康检查命令或脚本来确定的。例如,检查HTTP响应或数据连接等。
如果condition设置为service_completed_successfully,表示依赖服务成功完成后(即退出状态码为0),才会启动相关服务,通常用于数据库迁移、初始化脚本等。
required说明:
在长定义语法中,required字段用于指定依赖服务是否是必需的。它控制了当依赖服务未启动或不可用时的行为。
-
当 required 设置为 true(默认值),如果依赖服务未启动或不可用,Compose 将阻止启动相关的服务,并显示警告信息。
-
当 required 设置为 false,Compose 仍会显示警告信息,但不会阻止启动相关的服务。相当于它是可选的,即使依赖服务未启动或不可用,相关服务仍会尝试启动。
version: "1.1"services:mysql:image: mysqlcontainer_name: diJieXiaMysqlports:- "3710:3306"environment:TZ: Asia/ShanghaiMYSQL_ROOT_PASSWORD: 123volumes:- /opt/dijiexia_mysql/conf:/etc/mysql/conf.d #目录挂载MySQL的配置文件- /opt/dijiexia_mysql/data:/var/lib/mysql #目录挂载MySQL的数据- /opt/dijiexia_mysql/init:/docker-entrypoint-initdb.d #初始化数据库脚本挂载点,MySQL容器首次启动时,会自动执行.sh,.sql文件healthcheck:test: [ "CMD","mysqladmin","ping","-h","localhost" ]interval: 30stimeout: 3sretries: 3networks:- diJieXiaredis:image: rediscontainer_name: diJieXiaRedisports:- "3711:6379"volumes:- /opt/dijiexia_redis/conf/redis.conf:/usr/local/etc/redis/redis.conf- /opt/dijiexia_redis/data:/datacommand: [ "redis-server", "--requirepass", "123456" ]healthcheck:test: [ "CMD","redis-cli","ping" ]interval: 30stimeout: 3sretries: 3networks:- diJieXia#通过重新构建镜像的方式获取Go镜像,相当于docker build .dijiexia:build:context: .dockerfile: Dockerfilecontainer_name: diJieXiaProjectports:- "8001:8001"- "8000:8000"networks:- diJieXiavolumes:- ./conf:/confcommand:- RUN apk add --no-cache curlhealthcheck:test: [ "CMD","curl","-f","http://localhost:8000/api/v1/admin/captcha" ]interval: 30stimeout: 5sretries: 3depends_on:mysql:condition: service_healthyrequired: trueredis:condition: service_healthyrequired: truenginx:image: nginxcontainer_name: diJieXiaNginxports:- "3712:80"volumes:- /opt/dijiexia_front/nginx/conf/nginx.conf:/etc/nginx/nginx.conf #将nginx的配置文件nginx.conf挂载出来- /opt/dijiexia_front/nginx/conf.d:/etc/nginx/conf.d #挂载nginx的配置文件夹,通过在nginx.conf中的设置,会自动读取给目录下以.conf结尾的文件- /opt/dijiexia_front/nginx/html:/usr/share/nginx/html #将加载静态页面的目录挂载出来depends_on:dijiexia:condition: service_healthyrequired: falsenetworks:- diJieXianetworks:diJieXia:name: diJieXia111
volumes:diJieXiaRedisConf: { }diJieXiaRedisData: { }
当我再次使用docker compose up -d 运行的时候,会发现先启动MySQL、Redis容器,等到30秒之后,进行一次健康检测,发现MySQL和Redis都处于健康状态,之后才启动Project容器,等到Project容器健康检测后,最后启动Nginx容器。
通过condition和required参数,我们可以更加精准地控制容器编排的顺序。
相关文章:

Docekrfile和docker compose编写指南及注意事项
Dockerfile 基础语法 我们通过编写dockerfile,将每一层要做的事情使用语法固定下来,之后运行指令就可以通过docker来制作自己的镜像了。 构建镜像的指令:docker build /path -t imageName:tag 注意,docker build后的path必须是dockerfile…...
VITS源码解读6-训练推理
1. train.py 1.1 大体流程 执行main函数,调用多线程和run函数执行run函数,加载日志、数据集、模型、模型优化器for循环迭代数据batch,每次执行train_and_evaluate函数,训练模型 这里需要注意,源码中加载数据集用的分…...

力扣 简单 104.二叉树的最大深度
文章目录 题目介绍解法 题目介绍 解法 如果知道了左子树和右子树的最大深度 l 和 r,那么该二叉树的最大深度即为max(l,r)1,而左子树和右子树的最大深度又可以以同样的方式进行计算。因此我们可以用递归的方法来计算二叉树的最大深度。具体而言ÿ…...

单片机长短按简单实现
单片机长短按简单实现 目录 单片机长短按简单实现1 原理2 示例代码2.1 按键实现 3 测试log4 其他实现方式 1 原理 按键检测和处理的步骤如下: 1:定时扫描按键(使用定时器定时扫描,也可以用软件延时或者系统心跳之类的方式&#…...

如何用好通义灵码企业知识库问答能力?
通义灵码企业版:通义灵码企业标准版快速入门_智能编码助手_AI编程_智能编码助手通义灵码(Lingma)-阿里云帮助中心 通义灵码提供了基于企业知识库的问答检索增强的能力,在开发者使用通义灵码 IDE 插件时,可以结合企业知识库内上传的文档、文件…...

C语言自定义类型:联合体
目录 前言一、联合体1.1 联合体类型的声明1.2 联合体的特点1.3 相同成员的结构体和联合体对比1.4 联合体大小的计算1.5 联合体的⼀个练习 总结 前言 前面我讲到C语言中的自定义结构——结构体,其实C语言中的自定义结构不只有结构体,还有枚举和联合体&am…...

【JavaEE】——线程池大总结
阿华代码,不是逆风,就是我疯, 你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你! 目录 引入:问题引入 一:解决方案 1:方案一——协程/纤程 (1…...
编程中为什么使用0和1表示状态
前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 我们看到很多项目都使用0和1表示某些状态信息,具体含义取决于上下文。以下是一些常见的用法: 布尔值&#x…...

C++入门基础知识90(实例)——实例15【求两数的最大公约数】
成长路上不孤单😊😊😊😊😊😊 【14后😊///C爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于求两数的最大公约数的相关内容ÿ…...
自动化办公-Python-os模块的使用
os.path 模块的使用 在指定文件路径时,由于操作系统的差异,直接使用硬编码的路径可能会导致程序在不同平台上无法正常运行。为了解决这个问题,Python 提供了 os.path 模块,它包含了一系列用于路径操作的函数,可以帮助您…...

无人机之数据处理技术篇
一、数据采集 无人机通过搭载的各种传感器和设备,如GPS、加速度计、陀螺仪、磁力计、激光雷达(LiDAR)、高光谱相机(Hyperspectral)、多光谱相机(Multispectral)以及普通相机等,实时采集飞行过程中的各种数据。这些数据包括无人机的位置、速度、高度、姿态…...

828华为云征文|部署多功能集成的协作知识库 AFFiNE
828华为云征文|部署多功能集成的协作知识库 AFFiNE 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 AFFiNE3.1 AFFiNE 介绍3.2 AFFiNE 部署3.3 AFFiNE 使用 四、…...

c++(AVL树及其实现)
一、AVL树的概念 AVL树是最先发明的自平衡⼆叉查找树,AVL是⼀颗空树,或者具备下列性质的⼆叉搜索树:它的 左右子树都是AV树,且左右子树的高度差的绝对值不超过1。AVL树是⼀颗高度平衡搜索⼆叉树, 通过控制高度差去控…...
Cesium GIS项目关于湖泊识别与提取的实现
1. 引言 项目背景 随着遥感技术的发展,地理信息系统的应用越来越广泛。本项目旨在开发一个基于Cesium的地理信息系统,利用深度学习技术自动识别并显示湖泊的位置。 目标与意义 通过自动化处理大量遥感影像数据,提高湖泊监测的效率和准确性,为水资源管理和环境保护提供支…...
两个圆形 一个z里面一个z外面,z里面的大,颜色不同 html
两个圆形 一个z里面一个z外面,z里面的大,颜色不同 html <!DOCTYPE html> <html> <head> <style> .outer-circle {width: 150px;height: 150px;border-radius: 50%;background-color: #ff9999; /* 外圆的颜色 */position: relat…...
【Power Query】M函数-table
M函数-table 添加列(AddColumn):条件语句(If..then..else):容错语句(try..otherwise): 排序(ReorderColumns):筛选(Selec…...
uni-app 封装websocket 心跳检测,开箱即用
class websocketUtils {constructor(url, needbeat, options {}) {this.needbeat needbeat;this.url url;this.options options;this.ws null;this.heartbeatInterval options.heartbeatInterval || 10000; // 心跳间隔,默认为10秒 this.reconnectInterval …...

ASP.NET Core8.0学习笔记(十九)——EF Core DbSet
一、DbSet概述 1.DbSet提供了通过DbContext对表进行查询操作的路径。DbSet对应的属性名称将默认映射为实体T的表名。 2.使用DbSet<T>进行查询的方法: (1)直接在DbContext中创建对应的DbSet<T>属性 (2)使用DbSet DbContext.Set<T>方法操作数据表。…...
Android Camera 预览角度和拍照保存图片角度相关
–基于Android R(11) 关于Camera Camera Framework 的架构 Android Camera Framework 是一个分层架构,由以下组件组成: HAL(硬件抽象层): HAL 抽象底层相机硬件,提供与不同设备相机进行交互的标准接口.CameraService : Camera…...

新手如何使用Qt——方法使用
前言 那么这篇文章其实是我在使用Qt的过程当中呢,我发现在Qt使用过程中,在我理解信号和槽这个概念后,在编写槽函数数的时候,发现了自身存在的问题,我的难点是在于当我在编写槽函数的时候,我知道这个槽函数是…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...