目录结构
ToDoList
├── api
│ └── api.go
├── config
│ ├── config.go
│ ├── config.json
│ └── my.cnf
├── database
│ └── mysql.go
├── docker-compose.yml
├── Dockerfile
├── go.mod
├── go.sum
├── html
│ └── index.html
├── main.go
├── model
│ └── item.go
├── practice
│ ├── HelloWorld.go
│ └── Practice.go
├── README.md
├── resource
│ ├── css
│ │ └── style.css
│ └── js
│ ├── app.js
│ └── jquery-3.6.0.min.js
├── router
│ └── router.go
├── sql
│ ├── 000001_init_create_item_table.down.sql
│ ├── 000001_init_create_item_table.up.sql
│ └── init
│ └── item.sql
└── wait-for-it.sh
操作命令
docker-compose up
遇到的问题
-
每次运行项目时,需要执行两次
docker-compose up
,项目才能运行成功
第一次执行docker-compose up
时,会显示如下的错误dial tcp 172.23.0.02:3306: connect: connection refused
,第二次启动时才会正常。原因是尽管在docker-compose.yml
添加了depends_on
字段,depends_on: - mysql
但是
depends_on
字段仅能保证web
服务启动时,mysql
服务处于Running
状态而不是Ready
状态,因此需要添加一个脚本文件,检测mysql
服务是否处于Ready
状态。Docker官网给出的解决方案是在项目中添加一个wait-for-it.sh
脚本文件。按照官网建议,添加wait-for-it.sh并修改docker-compose.yaml
。command: ["./wait-for-it.sh", "mysql:3306", "--", "./main"]
-
standard_init_linux.go:219: exec user process caused: no such file or directory
在执行
docker-compose up
命令时,会遇到standard_init_linux.go:219: exec user process caused: no such file or directory
这个错误。
原因是Dockerfile
的第二阶段(运行阶段)选择scratch
作为起始镜像,scratch
是一个空镜像,并没有/bin/bash
命令,具体可参考Docker 底层镜像之选择困难症。
解决办法是选择alpine
作为起始镜像,并利用alpine
中的包管理工具apk
安装bash
。FROM alpine .... .... RUN apk update && apk add bash
-
数据库初始化
- 新建数据库
在docker-compose.yml
中,使用MYSQL_DATABASE
字段新建数据库mysql: image: mysql:5.7 restart: always environment: MYSQL_DATABASE: "todolist"
- 数据库配置
使用挂载方式添加数据库配置volumes: - ./config/my.cnf:/etc/conf.d # 数据库配置
- 新建数据表
使用挂载方式添加数据表初始化sqlvolumes: - ./sql/init:/docker-entrypoint-initdb.d/ # 数据库文件
- 新建数据库
代码
Dockerfile
FROM golang:1.16 as builder
MAINTAINER yanshan<ys_song@trip.com>
ENV GO111MODULE=on \
GOPROXY=https://goproxy.cn,direct
WORKDIR $GOPATH/src/ToDoList
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main .
RUN mkdir dst
RUN cp main dst && cp wait-for-it.sh dst && cp -r html dst && cp -r resource dst && cp -r config dst
FROM alpine
MAINTAINER yanshan<ys_song@trip.com>
ENV GIN_MOD=release
WORKDIR /DockerTest
RUN apk update && apk add bash
COPY --from=builder /go/src/ToDoList/dst .
EXPOSE 8080
docker-compose.yml
version: "3.3"
services:
todolist:
build: .
image: todolist
ports:
- 8080:8080
depends_on:
- mysql
command: ["./wait-for-it.sh", "mysql:3306", "--", "./main"]
mysql:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: "todolist"
MYSQL_ROOT_PASSWORD: "123456"
ports:
- 3306:3306
volumes:
- ./config/my.cnf:/etc/conf.d # 数据库配置
- ./sql/init:/docker-entrypoint-initdb.d/ # 数据库文件
main.go
package main
import (
. "ToDoList/config"
. "ToDoList/database"
. "ToDoList/router"
"net/http"
)
func main() {
InitConfig("config/config.json")
InitDatabase()
defer SqlDB.Close()
route := InitRouter()
// 引入html资源
route.LoadHTMLGlob("html/*")
// 引入静态资源
route.StaticFS("/resource", http.Dir("./resource"))
route.Run()
}
运行效果