基于docker搭建大项目本地开发环境
包括环境准备、中间件配置,打包部署
流程
- 前置准备
- 编写项目配置文件
- 配置文件解析工具类
- 部署 Sql 型数据库
- 部署 NoSql 型数据库
- 部署 OSS 对象存储
- 运行测试
- 编写 Dockerfile
- 打包成 Docker 镜像并运行
前置准备
简介
Docker是一种开源的容器化平台,它可以将应用程序及其所有的依赖打包到一个可移植的容器中。Docker容器可以在任何运行Docker的系统上运行,无论是在开发环境中的笔记本电脑上,还是在云服务器上。
使用Docker可以实现应用程序的快速部署、跨平台运行、环境隔离和资源管理等优势。通过创建一个Docker镜像,你可以定义一个应用程序运行所需的所有环境和设置,然后使用这个镜像在任何地方运行你的应用程序,而不必担心环境的差异或依赖的安装。
在Docker中,使用Dockerfile来定义镜像的构建过程,包括基础镜像选择、安装依赖、配置环境等。然后,使用Docker命令可以方便地构建镜像、创建容器、启动、停止和管理容器。
系统要求
- 一台 linux 系统的计算机(WSL, Vmware 虚拟机,云服务器等),下面以 ubuntu 22.04 系统举例
- 建议配置 内存 >= 1G, 硬盘 >= 20G
下载 docker
- 网上的相关资源很多,这里给出一个示例
# 更新软件包索引
sudo apt update
# 安装必要的软件包
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
# 添加Docker官方的GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 添加Docker的稳定存储库
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 更新软件包索引
sudo apt update
# 安装Docker Engine
sudo apt install -y docker-ce docker-ce-cli containerd.io
# 验证Docker是否成功安装并正在运行
sudo docker run hello-world
- 配置 docker 镜像加速
单机环境 docker 的基本命令
- 显示信息
docker info
docker version
systemctl status docker
- 显示镜像
docker images
- 搜索镜像
docker search xx
- 拉取镜像
docker pull xx:version
- 删除镜像
docker rmi 镜像名
操作容器
- 查看所有容器
docker ps -a
- 运行容器
# 创建容器
docker run -id --name==容器名 镜像名
# 进入容器
docker exec -it 容器名 /bin/bash
#常用参数说明
--name="Name" # 容器名字 例如:tomcat01 tomcat02 用来区分容器
-i # 保持运行
-d # 后台方式运行
-t # 分配一个命令行,使用交互方式运行
-p(小写p) # 指定容器的端口
-P(大写P) # 随机指定端口
-v [宿主机绝对路径]:[容器中路径] # 挂载数据卷
# 退出
exit #退出容器并停止
- 修改容器
docker start 容器ID # 启动容器
docker restart 容器ID # 重启容器
docker stop 容器ID # 停止当前正在运行的容器
docker kill 容器ID # 强制停止当前的容器
# 删除容器
docker rm c1
# 查看容器信息
docker inspect c1
编写项目的配置文件
- 以技术栈 gin+gorm+mysql+redis+mongoDB+minio 为例
- 将 config.yml 放在根目录下,与 main.go, go.mod 并列
- config.yml 配置内容示例,根据需要替换ip(docker 宿主机的ipv4地址), 端口,数据库密码等信息
gin:
port: 8080
database:
host: ip
port: 3306
username: root
password: 123456
name: douyin
redis:
address: ip:6379
db: 0
mongodb:
uri: mongodb://ip:27017
username: root
password: 123456
database: admin
minio:
server: ip:9000
accessKey: xxx
secretKey: xxx
配置文件读取工具类
- 根目录/util/config_reader.go 示例
package util
import (
"github.com/spf13/viper"
)
// Config 配置结构体
type Config struct {
Gin GinConfig `mapstructure:"gin"`
Database DatabaseConfig `mapstructure:"database"`
MinIO MinIOConfig `mapstructure:"minio"`
Mongo MongoDBConfig `mapstructure:"mongodb"`
Redis RedisConfig `mapstructure:"redis"`
}
// GinConfig Gin配置结构体
type GinConfig struct {
Port int `mapstructure:"port"`
}
// DatabaseConfig 数据库配置结构体
type DatabaseConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Name string `mapstructure:"name"`
}
// MinIOConfig MinIO配置结构体
type MinIOConfig struct {
Server string `mapstructure:"server"`
AccessKey string `mapstructure:"accessKey"`
SecretKey string `mapstructure:"secretKey"`
}
// MongoDBConfig MongoDB配置结构体
type MongoDBConfig struct {
URI string `mapstructure:"uri"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Database string `mapstructure:"database"`
}
// RedisConfig Redis配置结构体
type RedisConfig struct {
Address string `mapstructure:"address"`
DB int `mapstructure:"db"`
}
// LoadConfig 加载配置文件
func LoadConfig() (*Config, error) {
var config Config
viper.SetConfigName("config") // 配置文件名称(不带后缀)
viper.AddConfigPath(".") // 配置文件所在路径
viper.SetConfigType("yml") // 配置文件类型(yaml、json、toml等)
if err := viper.ReadInConfig(); err != nil {
return nil, err
}
if err := viper.Unmarshal(&config); err != nil {
return nil, err
}
return &config, nil
}
- 使用 config
func main() {
config, err := util.LoadConfig()
if err != nil {
log.Fatal(err)
}
// 使用配置进行连接
}
docker 部署 Sql 数据库
- 停止本机原有的服务(若与本机端口冲突), 下同
sudo service mysql stop
sudo systemctl stop mysql
- 拉取镜像
docker pull mysql
- 启动容器, 自行配置容器名和 root 密码和挂载目录, 下同
docker run --name mysql-server \
-e MYSQL_ROOT_PASSWORD=123456 \
-p 3306:3306 \
-v mysql/conf/my.conf:/etc/mysql/conf.d/my.conf \
-v mysql/data:/var/lib/mysql \
-d \
mysql
docker 部署 NoSql
部署 redis
- 拉取镜像
docker pull redis
- 启动容器, 自行配置容器名和挂载目录
docker run -d --name redis -p 6379:6379 \
--privileged=true \
-v /redis/data:/data --restart always redis \
--appendonly yes
部署 mongoDB
- 拉取镜像
docker pull mongo:4.4
- 启动容器, 自行配置容器名和挂载目录
docker run -itd --name mongo -v mongodb/data:/data/db -p 27017:27017 mongo:4.4 --auth
- 创建用户
docker exec -it mongo mongo admin
# 默认无用户,创建一个。详细的命令含义参考 mongoDB 官方文档
db.createUser({ user:'root',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},'readWriteAnyDatabase']});
db.auth('root', '123456');
参考链接:blog.csdn.net/packge/arti…
部署 OSS 对象存储
MinIO是一个开源的对象存储服务器,它实现了Amazon S3(Simple Storage Service)云存储服务的API。它致力于提供高性能、高可用性和可扩展性的存储解决方案,可以用于构建私有云存储、备份和归档、大规模数据分析等应用。
兼容性:MinIO提供了与Amazon S3兼容的API,意味着您可以使用已经支持Amazon S3的工具和应用来访问和管理MinIO服务器。
开源:MinIO完全开源,使用Apache License 2.0许可证。这意味着您可以自由地查看、修改和分发代码。
分布式存储:MinIO可以在多个节点上部署,创建一个分布式存储系统。它支持数据的分片,将数据均匀地分布在不同的节点上,以实现高可用性和可扩展性。
高性能:MinIO使用Go语言编写,具有出色的性能和低延迟。它能够利用现代硬件的多核处理能力和高速网络连接,提供快速的数据传输和处理。
- 拉取镜像
docker pull minio/minio
- 运行容器
docker run -p 9090:9000 -p 9001:9001 --name minio \
-v /minio/data:/data \
-e MINIO_ROOT_USER=minio \
-e MINIO_ROOT_PASSWORD=123456 \
-d minio/minio server /data --console-address ":9001"
- 访问 http://{docker宿主机IP}:9000 进入 UI 控制台继续完成下面操作
- 创建 access-key 和 secret-key 用于客户端认证
- 创建 bucket 等
部署其他中间件
如有需要参考上面的步骤配置 MQ, API gateway 等,此处略
运行测试
- 检查 docker 容器启动
root@ubuntu-22.04:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
279da23cac51 minio/minio "/usr/bin/docker-ent…" 2 hours ago Up 2 hours 0.0.0.0:9000-9001->9000-9001/tcp, :::9000-9001->9000-9001/tcp minio
e28f9e51b7ca redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis-server
7714aee4745c mysql "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql-server
9c6cbb18801c mongo:4.4 "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:27017->27017/tcp, :::27017->27017/tcp mongodb
go 项目中根据配置文件连接到部署的docker容器,在本地进行代码开发,依赖的中间件全部由另一台计算机的 docker 进行管理。
同时可以使用 Datagrip 等数据库UI连接到 docker 容器。实现分离开发
为项目编写 Dockerfile
-
Dockerfile 是一种文本配置文件,用于定制镜像。详细的参数含义参考 docker 官方文档
-
在项目根目录中创建文件 Dockerfile
-
Go web项目的示例Dockerfile 如下:
# 设置基础镜像
FROM golang:1.20.0-alpine as build
# 指定go的环境变量
ENV GOPROXY=https://goproxy.cn \
GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
# 可以自定义其他环境变量
# 指定工作空间目录,会自动cd到这个目录
WORKDIR /build
# 把项目的依赖配置文件拷贝到容器中,并下载依赖
COPY go.mod .
COPY go.sum .
RUN go mod download
# 把项目的其他所有文件拷贝到容器中
COPY . .
# 编译成可执行二进制文件
RUN go build -o app .
# 指定新的运行环境,最终的运行会基于这个坏境,使得最终的镜像非常小
FROM scratch as deploy
# 把编译环境中打包好的可执行文件和配置文件拷贝到当前镜像
COPY --from=build /build/app /
COPY --from=build /build/config.yml ./config.yml
CMD ["/app"]
打包发布镜像
- 将项目根目录压缩为 zip 文件
- 使用 scp 等指令将 zip 文件上传到 linux 设备中并解压
- 继续 cd到项目根目录,创建镜像
docker build . -t douyin-server
- 创建容器
docker run -itd --name douyin -p 8080:8080 douyin-server
- 查看结果
root@VM-8-11-ubuntu:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
89fc75ba6a22 douyin-server "/app" 2 hours ago Up 2 hours 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp douyin
- app 输入baseURL http://{docker宿主机IP}:8080 即可访问项目