当然,下面是优化后的项目文件夹结构,包含了配置文件夹、Go 项目文件夹、Redis 数据持久化以及独立的环境配置文件。
文件夹结构
myapp/
├── Dockerfile
├── docker-compose.yml
├── .env
├── redis/
│ └── redis.conf
├── mysql/
│ └── init.sql
└── src/
└── main.go
1. Dockerfile
用于构建 Go 应用的 Docker 镜像。
FROM golang:1.19
WORKDIR /app
LABEL maintainer="cwx@email.com"
#这一步可以改成从仓库克隆代码
COPY ./src/ /app
# || true 的作用是确保即使 go mod init myapp 失败,Docker 构建过程也不会因为这一行而停止。
RUN go mod init myapp.com || true
RUN go mod tidy
RUN go build -o main .
EXPOSE 8080
CMD ["./main"]
注意📢:
docker build: 执行 Dockerfile 中的FROM,WORKDIR,LABEL,COPY,RUN, 和EXPOSE等命令来构建镜像。docker run: 执行 Dockerfile 中的CMD和ENTRYPOINT等命令来启动容器。
所以,如果是在主机改动了 Go 项目代码,就必须得重新 build 新的镜像,然后再执行。
所以,这里推荐使用通过 goland 进行远程连接到容器内,使用容器内的代码来改动调试,一并配置好远程 GO 调试和语法检测,那么本地就可以无任何编程环境的情况下,运行调试起来!
由于改的是容器内的代码,所以在容器内直接重新编译更新就好了!
2. docker-compose.yml
定义 Go 应用、MySQL 数据库和 Redis 缓存服务。
# docker-compose.yml
version: '3.8'
services:
app:
build: .
container_name: go-app
ports:
- "8080:8080"
env_file:
- .env
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks:
- mynetwork
db:
image: mysql:8.0
container_name: mysql-db
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_DATABASE: mydatabase
volumes:
- dbdata:/var/lib/mysql
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- mynetwork
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 30s
timeout: 10s
retries: 3
redis:
image: redis:latest
container_name: redis-cache
volumes:
- redisdata:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
networks:
- mynetwork
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
dbdata:
redisdata:
networks:
mynetwork:
driver: bridge
3. Go 应用代码
src/main.go 包含连接 MySQL 和 Redis 的示例代码。
package main
import (
"database/sql"
"fmt"
"log"
"net/http"
"os"
redis "github.com/go-redis/redis/v8"
_ "github.com/go-sql-driver/mysql"
"golang.org/x/net/context"
)
var (
db *sql.DB
rdb *redis.Client
ctx = context.Background()
)
func main() {
// 读取环境变量
mysqlURL := os.Getenv("MYSQL_URL")
redisURL := os.Getenv("REDIS_URL")
// 初始化 MySQL 连接
var err error
db, err = sql.Open("mysql", mysqlURL)
if err != nil {
log.Fatalf("Error opening MySQL connection: %v", err)
}
defer db.Close()
// 初始化 Redis 连接
// 使用redis.ParseURL函数解析Redis URI
opts, err := redis.ParseURL(redisURL)
if err != nil {
log.Fatalf("Error parsing Redis URL: %v", err)
}
// 创建Redis客户端
rdb = redis.NewClient(opts)
// 使用Redis客户端执行操作,例如Ping
pong, err := rdb.Ping(ctx).Result()
if err != nil {
log.Fatalf("Error pinging Redis: %v", err)
}
log.Println("Redis ping response:", pong)
// 设置 HTTP 处理器
http.HandleFunc("/", handleRequest)
// 启动 HTTP 服务器
err = http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatalf("Error starting HTTP server: %v", err)
}
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
// 从 Redis 读取数据
redisValue, err := rdb.Get(ctx, "key").Result()
if err != nil && err != redis.Nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 从 MySQL 查询数据
var now string
err = db.QueryRow("SELECT NOW()").Scan(&now)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 响应客户端
fmt.Fprintf(w, "Current time from MySQL: %s\n", now)
fmt.Fprintf(w, "Value from Redis: %s\n", redisValue)
}
4. 环境配置文件
.env 文件包含环境变量配置。
MYSQL_URL="user:password@tcp(db:3306)/mydatabase?charset=utf8mb4"
REDIS_URL=redis://123456@redis:6379
5. Redis 配置文件
redis/redis.conf 配置 Redis(可选)。
# redis.conf
# redis.conf
# Bind to all interfaces
bind 0.0.0.0
# Listening port
port 6379
# Require clients to authenticate with this password
requirepass 123456
# Directory for storing data
dir /data
# Dump file name
dbfilename dump.rdb
# Append only file configuration
appendonly yes
# Memory management
maxmemory 400mb
maxmemory-policy allkeys-lru
# 使用默认配置
6. MySQL 初始化脚本
mysql/init.sql 用于初始化 MySQL 数据库(可选)。
-- init.sql
CREATE TABLE IF NOT EXISTS test (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
INSERT INTO test (name) VALUES ('initial data');
使用步骤
- 创建文件:
-
- 在项目目录中创建上述所有文件。
- 构建和启动服务:
-
- 在项目目录中运行
docker-compose命令构建镜像并启动服务:
- 在项目目录中运行
docker-compose up --build
- 访问 Go 应用:
-
- 打开浏览器,访问
http://localhost:8080,查看 Go 应用的输出。
- 打开浏览器,访问
优点
- 清晰的组织结构:将不同类型的文件放在不同的文件夹中,方便管理和维护。
- 持久化数据:Redis 和 MySQL 的数据都被持久化到 Docker 卷中,不会因容器重启而丢失。
- 环境变量管理:使用
.env文件管理环境变量,使得配置更为灵活和安全。
这个示例展示了如何使用 Docker 和 docker-compose 来创建一个包含 Go 应用、MySQL 和 Redis 的综合环境,并提供了改进后的文件结构和配置示例。
---
总结
通过以上步骤就可以搭建一个完成的 Go 项目开发环境了,可以把上述项目文件上传到公司的 Git 仓库,组内小伙伴克隆这个项目,然后 docker-compose up 就可以启动一个项目啦。
使用 Goland 或者 vsCode 进行远程连接,接入到 docker go 容器里面进行拉取代码修改(注意要改容器内的代码),再配置好远程 Go 编译和语法检测,那么本地就可以无任何开发环境的情况下,进行 Go 代码编写以及调试啦!
由于改的是容器内的代码,所以在容器内直接重新编译更新就好了!