在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-slim

COPY ./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.conf
    command: "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.conf
  go-api:
    # 容器名
    container_name: go-web-api
    build:
      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 available

WAITFORIT_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 test
                                Alternatively, 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=TIMEOUT
                                Timeout in seconds, zero for no timeout
    -- COMMAND ARGS             Execute command with args after the test finishes
USAGE
    exit 1
}

wait_for()
{
    if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
        echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
    else
        echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
    fi
    WAITFORIT_start_ts=$(date +%s)
    while :
    do
        if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
            nc -z $WAITFORIT_HOST $WAITFORIT_PORT
            WAITFORIT_result=$?
        else
            (echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
            WAITFORIT_result=$?
        fi
        if [[ $WAITFORIT_result -eq 0 ]]; then
            WAITFORIT_end_ts=$(date +%s)
            echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
            break
        fi
        sleep 1
    done
    return $WAITFORIT_result
}

wait_for_wrapper()
{
    # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
    if [[ $WAITFORIT_QUIET -eq 1 ]]; then
        timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
    else
        timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
    fi
    WAITFORIT_PID=$!
    trap "kill -INT -$WAITFORIT_PID" INT
    wait $WAITFORIT_PID
    WAITFORIT_RESULT=$?
    if [[ $WAITFORIT_RESULT -ne 0 ]]; then
        echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
    fi
    return $WAITFORIT_RESULT
}

# process arguments
while [[ $# -gt 0 ]]
do
    case "$1" in
        *:* )
        WAITFORIT_hostport=(${1//:/ })
        WAITFORIT_HOST=${WAITFORIT_hostport[0]}
        WAITFORIT_PORT=${WAITFORIT_hostport[1]}
        shift 1
        ;;
        --child)
        WAITFORIT_CHILD=1
        shift 1
        ;;
        -q | --quiet)
        WAITFORIT_QUIET=1
        shift 1
        ;;
        -s | --strict)
        WAITFORIT_STRICT=1
        shift 1
        ;;
        -h)
        WAITFORIT_HOST="$2"
        if [[ $WAITFORIT_HOST == "" ]]; then break; fi
        shift 2
        ;;
        --host=*)
        WAITFORIT_HOST="${1#*=}"
        shift 1
        ;;
        -p)
        WAITFORIT_PORT="$2"
        if [[ $WAITFORIT_PORT == "" ]]; then break; fi
        shift 2
        ;;
        --port=*)
        WAITFORIT_PORT="${1#*=}"
        shift 1
        ;;
        -t)
        WAITFORIT_TIMEOUT="$2"
        if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
        shift 2
        ;;
        --timeout=*)
        WAITFORIT_TIMEOUT="${1#*=}"
        shift 1
        ;;
        --)
        shift
        WAITFORIT_CLI=("$@")
        break
        ;;
        --help)
        usage
        ;;
        *)
        echoerr "Unknown argument: $1"
        usage
        ;;
    esac
done

if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
    echoerr "Error: you need to provide a host and port to test."
    usage
fi

WAITFORIT_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" ]]; then
    WAITFORIT_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 '; then
        WAITFORIT_BUSYTIMEFLAG="-t"
    fi
else
    WAITFORIT_ISBUSY=0
fi

if [[ $WAITFORIT_CHILD -gt 0 ]]; then
    wait_for
    WAITFORIT_RESULT=$?
    exit $WAITFORIT_RESULT
else
    if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
        wait_for_wrapper
        WAITFORIT_RESULT=$?
    else
        wait_for
        WAITFORIT_RESULT=$?
    fi
fi

if [[ $WAITFORIT_CLI != "" ]]; then
    if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
        echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
        exit $WAITFORIT_RESULT
    fi
    exec "${WAITFORIT_CLI[@]}"
else
    exit $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;

推荐文章:Go服务部署-Docker部署


本文由 一切随风 创作,可自由转载、引用,但需署名作者且注明文章出处。

25 条评论

  1. tr
    tr

    ███ ㊙️ ███ 㸔 黃 魸【 T55V.CC 】浏 览 噐 咑 开【 T55V.CC 】免 ِ曊 ِ㸔 ███ ㊙️ ███

  2. fdxvgdgd
    fdxvgdgd

    █ █ █ 幼 女 资 源 在 线 观 看【 w w w . 3 p u . b i z 】 █ █ █

  3. 鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099
    鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099

    新盛客服电话是多少?(?183-8890-9465—《?薇-STS5099】【
    新盛开户专线联系方式?(?183-8890--9465—《?薇-STS5099】【?扣6011643??】
    新盛客服开户电话全攻略,让娱乐更顺畅!(?183-8890--9465—《?薇-STS5099】客服开户流程,华纳新盛客服开户流程图(?183-8890--9465—《?薇-STS5099】

  4. 鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099
    鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099

    华纳东方明珠客服电话是多少?(▲18288362750?《?微信STS5099? 】
    如何联系华纳东方明珠客服?(▲18288362750?《?微信STS5099? 】
    华纳东方明珠官方客服联系方式?(▲18288362750?《?微信STS5099?
    华纳东方明珠客服热线?(▲18288362750?《?微信STS5099?
    华纳东方明珠24小时客服电话?(▲18288362750?《?微信STS5099? 】
    华纳东方明珠官方客服在线咨询?(▲18288362750?《?微信STS5099?

  5. 鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099
    鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099

    华纳东方明珠客服电话是多少?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠开户专线联系方式?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    如何联系华纳东方明珠客服?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠官方客服联系方式?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠客服热线?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠开户客服电话?(▲182(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠24小时客服电话?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠客服邮箱?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠官方客服在线咨询?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠客服微信?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】

  6. 鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099
    鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099

    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099

  7. 鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099
    鍗庣撼鍏徃鍚堜綔寮€鎴锋墍闇€鏉愭枡锛熺數璇濆彿鐮?5587291507 寰俊STS5099

    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099

  8. bmowenavtn
    bmowenavtn

    妖猫传

  9. mdmbjlemzt
    mdmbjlemzt

    彩虹

  10. bmhipvckry
    bmhipvckry

    内特巴加兹的纳什维尔圣诞节

  11. foqlnowqsh
    foqlnowqsh

    白发魔女传

  12. omdenhiuop
    omdenhiuop

    暗影之地

  13. ndwubzkrlj
    ndwubzkrlj

    海滩救护队

  14. huuquitrmk
    huuquitrmk

    新警察故事

  15. zxavdfqozr
    zxavdfqozr

    css教程

  16. pxnehimacg
    pxnehimacg

    鬼眼日记

  17. ugvthausmq
    ugvthausmq

    911世界停滞之日

  18. qnvaovbccq
    qnvaovbccq

    因果报应

  19. ythgulkwwz
    ythgulkwwz

    你的才华让人瞩目,期待你的更多文章。 http://www.55baobei.com/hD9XdToPIf.html

  20. fsrdvgvmzw
    fsrdvgvmzw

    《比尔伯尔:纸老虎》欧美综艺高清在线免费观看:https://www.jgz518.com/xingkong/121683.html

  21. upqpgsrdbi
    upqpgsrdbi

    你的才华横溢,让人敬佩。 https://www.yonboz.com/video/56230.html

  22. bkqxppgmkc
    bkqxppgmkc

    《迷离无迹》恐怖片高清在线免费观看:https://www.jgz518.com/xingkong/16049.html

  23. cbpbazxjji
    cbpbazxjji

    你的文章让我感受到了正能量,非常棒! https://www.yonboz.com/video/74479.html

  24. kztzexvuuc
    kztzexvuuc

    《大汉天子2:汉武雄风》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/37626.html

  25. fxohdefnui
    fxohdefnui

    想想你的文章写的特别好https://www.ea55.com/

添加新评论