Docker compose部署Golang服务
Docker Compose 部署
在使用docker部署时,除了使用--link
的方式来关联容器之外,还可以使用 docker compose 运行多个容器。
本文以项目:https://github.com/johncxf/go-api 为例。
定义 Dockerfile
我这里用于区分默认 Dockerfile 文件,在项目根目录下新建一个 Dockerfile-compose 文件:
FROM golang:alpine AS builder# 在容器内部设置环境变量
ENV GO111MODULE=on \GOPROXY=https://goproxy.cn,direct \CGO_ENABLED=0 \GOOS=linux \GOARCH=amd64# 设置后续指令的工作目录
WORKDIR /build# 复制项目中的 go.mod 和 go.sum文件并下载依赖信息
COPY go.mod .
COPY go.sum .
RUN go mod download# 将代码复制到容器中
COPY . .# 将代码编译成二进制可执行文件
RUN go build -o go-api .# 创建一个小镜像
#FROM scratch
FROM debian:stretch-slimCOPY ./config /config# 从builder镜像中把 /build/go-api 拷贝到当前目录
COPY --from=builder /build/go-api /# 需要运行的命令(docker compose 运行不需要执行这一行)
#ENTRYPOINT ["/go-api", "config/env.yml"]
docker-compose.yml
新建 docker-compose.yml
配置文件与项目根目录下。
我这里配置了mysql、redis、go-api三个容器,配置以及说明如下:
version: "3.7"
services:mysql:# 镜像版本号image: mysql:8.0.33# 容器名container_name: go-web-mysql# 端口号映射ports:- "8306:3306"# 失败后总是重启restart: "always"command: "--default-authentication-plugin=mysql_native_password --init-file /data/application/init.sql"environment:MYSQL_ROOT_PASSWORD: "root123456" # root 账号密码MYSQL_DATABASE: "test" # 数据库# 将mysql相关数据挂载到本机目录volumes:- ~/docker-data/go-api/mysql/init.sql:/data/application/init.sql- ~/docker-data/go-api/mysql/data:/var/lib/mysql #数据文件挂载- ~/docker-data/go-api/mysql/conf.d:/etc/mysql/conf.d #配置文件挂载- ~/docker-data/go-api/mysql/log:/var/log/mysql #日志文件挂载redis:# 镜像版本号image: redis:7.2.4# 容器名container_name: go-web-redis# 端口号ports:- "6379:6379"# 失败后总是重启restart: "always"# 以配置文件的方式启动 redis.confcommand: "redis-server /etc/redis/redis.conf --appendonly yes --requirepass root123456"# 文件夹以及文件映射volumes:- ~/docker-data/go-api/redis:/data- ~/docker-data/go-api/redis/redis.conf:/etc/redis/redis.confgo-api:# 容器名container_name: go-web-apibuild:context: .dockerfile: Dockerfile-compose # 默认为 Dockerfile,这里重新定义为 Dockerfile-compose 文件# 失败后总是重启restart: "always"# command: sh -c "./wait-for-it.sh mysql:3306 -- ./go-api ./config/env.yml"command: [ "/wait-for-it.sh", "mysql:3306", "--", "/go-api", "config/env.yml" ]# 依赖启动项depends_on:- mysql- redis# 端口映射ports:- "8888:8088"
Mysql 状态检测
docker-compose.yml 配置文件中 depends_on
字段仅能保证web服务启动时,mysql服务处于Running状态而不是Ready状态,因为go-api需要等待mysql启动后再启动,因此需要添加一个wait-for-it.sh
脚本文件,检测mysql服务是否处于Ready状态。
在项目根目录下新建 wait-for-it.sh
文件:
#!/usr/bin/env bash
# Use this script to test if a given TCP host/port are availableWAITFORIT_cmdname=${0##*/}echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }usage()
{cat << USAGE >&2
Usage:$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]-h HOST | --host=HOST Host or IP under test-p PORT | --port=PORT TCP port under testAlternatively, you specify the host and port as host:port-s | --strict Only execute subcommand if the test succeeds-q | --quiet Don't output any status messages-t TIMEOUT | --timeout=TIMEOUTTimeout in seconds, zero for no timeout-- COMMAND ARGS Execute command with args after the test finishes
USAGEexit 1
}wait_for()
{if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; thenechoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"elseechoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"fiWAITFORIT_start_ts=$(date +%s)while :doif [[ $WAITFORIT_ISBUSY -eq 1 ]]; thennc -z $WAITFORIT_HOST $WAITFORIT_PORTWAITFORIT_result=$?else(echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1WAITFORIT_result=$?fiif [[ $WAITFORIT_result -eq 0 ]]; thenWAITFORIT_end_ts=$(date +%s)echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"breakfisleep 1donereturn $WAITFORIT_result
}wait_for_wrapper()
{# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692if [[ $WAITFORIT_QUIET -eq 1 ]]; thentimeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &elsetimeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &fiWAITFORIT_PID=$!trap "kill -INT -$WAITFORIT_PID" INTwait $WAITFORIT_PIDWAITFORIT_RESULT=$?if [[ $WAITFORIT_RESULT -ne 0 ]]; thenechoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"fireturn $WAITFORIT_RESULT
}# process arguments
while [[ $# -gt 0 ]]
docase "$1" in*:* )WAITFORIT_hostport=(${1//:/ })WAITFORIT_HOST=${WAITFORIT_hostport[0]}WAITFORIT_PORT=${WAITFORIT_hostport[1]}shift 1;;--child)WAITFORIT_CHILD=1shift 1;;-q | --quiet)WAITFORIT_QUIET=1shift 1;;-s | --strict)WAITFORIT_STRICT=1shift 1;;-h)WAITFORIT_HOST="$2"if [[ $WAITFORIT_HOST == "" ]]; then break; fishift 2;;--host=*)WAITFORIT_HOST="${1#*=}"shift 1;;-p)WAITFORIT_PORT="$2"if [[ $WAITFORIT_PORT == "" ]]; then break; fishift 2;;--port=*)WAITFORIT_PORT="${1#*=}"shift 1;;-t)WAITFORIT_TIMEOUT="$2"if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fishift 2;;--timeout=*)WAITFORIT_TIMEOUT="${1#*=}"shift 1;;--)shiftWAITFORIT_CLI=("$@")break;;--help)usage;;*)echoerr "Unknown argument: $1"usage;;esac
doneif [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; thenechoerr "Error: you need to provide a host and port to test."usage
fiWAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}# Check to see if timeout is from busybox?
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)WAITFORIT_BUSYTIMEFLAG=""
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; thenWAITFORIT_ISBUSY=1# Check if busybox timeout uses -t flag# (recent Alpine versions don't support -t anymore)if timeout &>/dev/stdout | grep -q -e '-t '; thenWAITFORIT_BUSYTIMEFLAG="-t"fi
elseWAITFORIT_ISBUSY=0
fiif [[ $WAITFORIT_CHILD -gt 0 ]]; thenwait_forWAITFORIT_RESULT=$?exit $WAITFORIT_RESULT
elseif [[ $WAITFORIT_TIMEOUT -gt 0 ]]; thenwait_for_wrapperWAITFORIT_RESULT=$?elsewait_forWAITFORIT_RESULT=$?fi
fiif [[ $WAITFORIT_CLI != "" ]]; thenif [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; thenechoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"exit $WAITFORIT_RESULTfiexec "${WAITFORIT_CLI[@]}"
elseexit $WAITFORIT_RESULT
fi
构建启动
# 会根据 docker-compose 文件,构建镜像,并启动所有容器
$ docker-compose up -d# 查看容器
$ docker-compose ps -a# 停止所有容器
$ docker-compose down
启动成功后,接下来就可以通过http://127.0.0.1:8888
进行访问了。
如果连接 Mysql 出现报错,可以参考:
Msql 进入容器使用 127.0.0.1
连接mysql报错:ERROR 1130 (HY000): Host '127.0.0.1' is not allowed to connect to this MySQL server
,可以直接输入 mysql
进入,执行以下操作:
> use mysql;
> update user set host = '%' where user = 'root';
> FLUSH PRIVILEGES;
Mysql root 密码设置不生效解决:
> use mysql;
> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root123456';
> FLUSH PRIVILEGES;
文章推荐:
- Docker部署Golang服务
- Docker 入门指南
- Docker compose 常用指令
相关文章:
Docker compose部署Golang服务
Docker Compose 部署 在使用docker部署时,除了使用--link的方式来关联容器之外,还可以使用 docker compose 运行多个容器。 本文以项目:https://github.com/johncxf/go-api 为例。 定义 Dockerfile 我这里用于区分默认 Dockerfile 文件&a…...

Day36 435无重叠区间 763划分字母区间
435 无重叠区间 给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。 注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。 本题与上一题类似: 如果按照左…...

【Servlet】如何编写第一个Servlet程序
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【Servlet】 本专栏旨在分享学习Servlet的一点学习心得,欢迎大家在评论区交流讨论💌 Servlet是Java编写的服务器端…...

读懂比特币—bitcoin代码分析(五)
今天的代码分析主要是 bitcoin/src/init.cpp 文件中的三个函数:AppInitSanityChecks、AppInitLockDataDirectory、AppInitInterfaces,下面我们来说明这三个函数是用来干什么的,并逐行解读函数代码,先贴出源代码如下: …...
uniapp使用uQRCode插件生成二维码的简单使用
最近在找移动端绘制二维码的问题 ,直接上代码 下载 weapp-qrcode.js(可以通过npm install weapp-qrcode --save 下载,之后把它父子到untils目录下) npm install weapp-qrcode --save在组件页面使用 <canvas id"couponQrcode" canvas-id&qu…...

【寒假每日一题·2024】AcWing 4965. 三国游戏(补)
文章目录 一、题目1、原题链接2、题目描述 二、解题报告1、思路分析2、时间复杂度3、代码详解 一、题目 1、原题链接 4965. 三国游戏 2、题目描述 二、解题报告 1、思路分析 思路参考y总:y总讲解视频 (1)题目中的获胜情况分为三种ÿ…...
docker 安装mongodb 数据库
1.拉取mongodb镜像 docker pull mongo2.创建文件夹 mkdir -p /home/mongo/conf/ mkdir -p /home/mongo/data/ mkdir -p /home/mongo/logs/3.新增mongod.conf文件 cd /home/mongo/conf && vi mongod.confmongod.conf文件内容: # 数据库文件存储位置 dbpa…...
整数反转算法(leetcode第7题)
题目描述: 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。假设环境不允许存储 64 位整数(有符号或无符号)。示例 1…...

微信小程序(十)表单组件(入门)
注释很详细,直接上代码 上一篇 新增内容: 1.type 属性指定表单类型 2.placeholder 属性指定输入框为空时的占位文字 源码: form.wxml <!-- 提前准备好的布局结构代码 --> <view class"register"><view class"…...

xcode 设置 ios苹果图标,为Flutter应用程序配置iOS图标
图标设置 1,根据图片构建各类尺寸的图标2.xcode打开ios文件3.xcode设置图标4.打包提交审核,即可(打包教程可通过我的主页查找) 1,根据图片构建各类尺寸的图标 工具网址:https://icon.wuruihong.com/ 下载之后文件目录如下 拷贝到项目的ios\Runner\Assets.xcassets\AppIcon.ap…...
什么是IDE?新手用哪个IDE比较好?
哈喽大家好,我是咕噜美乐蒂,很高兴又见面啦!今天我们来了解一下什么是IDE以及新手应该如何选择IDE比较合适。 一、什么是IDE? IDE(Integrated Development Environment,集成开发环境)是一种软…...

【数据库学习】pg安装与运维
1,安装与配置 #安装 yum install https:....rpm1)安装目录 bin目录:二进制可执行文件目录,此目录下有postgres、psql等可执行程序;pg_ctl工具在此目录,可以通过pg_ctl --help查看具体使用。 conf目录&…...

第二篇【传奇开心果短博文系列】Python的OpenCV库技术点案例示例:图像处理
传奇开心果短博文系列 系列短博文目录Python的OpenCV库技术点案例示例短博文系列 博文目录一、项目目标二、第一个示例代码三、第二个示例代码四、第三个示例代码五、第四个示例代码六、第五个示例代码七、知识点归纳总结 系列短博文目录 Python的OpenCV库技术点案例示例短博文…...

【vue oidc-client】invalid_requestRequest Id: 0HN0OOPFRLSF2:00000002
需求:完成统一登录,需要从三方平台跳到我们的平台。 oidc-client报错记录。这个一般是配置信息出错,需要和三方平台进行沟通,一定要把client_id,密钥进行对应; 同时关于此次出错还修改了以下代码ÿ…...
什么是中间人攻击? ssh 连接出现 Host key verification failed 解决方法
文章目录 前言known_hosts 文件是什么文件路径示例 连接出现 Host key verification failedssh-keygen -R [hostname or ip address]删除整个 known_hosts 文件 其它聊聊中间人攻击ssh 如何保证安全?加密流程漏洞在哪里如何避免中间人攻击 个人简介 前言 最近服务器…...
数据结构系统刷题
本文为系统刷leetcode的记录,会记录自己根据代码随想录刷过的leetcode,方便直接点开刷题,时常更新 时间复杂度简记为s 空间复杂度简记为k 数组 704 二分查找 一维二分查找 (1)[left, right] class Solution { publi…...

【RabbitMQ】延迟队列之死信交换机
🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《RabbitMQ实战》。🎯🎯 &am…...

2024交通运输工程与土木建筑工程国际会议(ICTECCE2024)
2024交通运输工程与土木建筑工程国际会议(ICTECCE2024) 会议简介 2024年国际交通工程和土木建筑工程会议(ICTECCE 2024)将在中国杭州举行。ICTECCE 2024致力于为交通工程和土木工程材料领域的学者、工程师和研究人员提供一个大型学术交流平台和双向交流…...

搜索引擎Elasticsearch了解
1.Lucene 是什么? 2.模块介绍 Lucene是什么: 一种高性能,可伸缩的信息搜索(IR)库 在2000年开源,最初由鼎鼎大名的Doug Cutting开发 是基于Java实现的高性能的开源项目 Lucene采用了基于倒排表的设计原理,可以非常高效地实现文本查找,在底层采用了分段的存储模式,使它在读…...

【操作系统基础】【CPU访存原理】:寄存 缓存 内存 外存、内存空间分区、虚拟地址转换、虚拟地址的映射
存储器怎么存储数据、内存空间分区、虚拟地址转换 计算机的存储器:寄存 缓存 内存 外存(按功能划分) 计算机的处理器需要一个存储器来存储大量的指令和数据以便自己不断取指执行和访问数据。 内存(内存就是运行内存,…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...