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访存原理】:寄存 缓存 内存 外存、内存空间分区、虚拟地址转换、虚拟地址的映射
存储器怎么存储数据、内存空间分区、虚拟地址转换 计算机的存储器:寄存 缓存 内存 外存(按功能划分) 计算机的处理器需要一个存储器来存储大量的指令和数据以便自己不断取指执行和访问数据。 内存(内存就是运行内存,…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
6.9-QT模拟计算器
源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...
Vue 3 + WebSocket 实战:公司通知实时推送功能详解
📢 Vue 3 WebSocket 实战:公司通知实时推送功能详解 📌 收藏 点赞 关注,项目中要用到推送功能时就不怕找不到了! 实时通知是企业系统中常见的功能,比如:管理员发布通知后,所有用户…...
