目前我们公司已经深度的使用 Docker 来部署项目,在推进 Docker 落地的过程中,如何将 Docker 的配置文件更好的融入项目一直是困扰着我们的问题。
刚开始我们把 Docker 配置文件全部一股脑地放在项目里, 使编程架构和部署架构给混在了一起,如果开发和部署是一拨人倒还好,如果开发和部署是分开的两个工种,这种方式会造成一定程度的混乱。
以我们 Laravel 项目目录结构为例
.
├── app
├── artisan
├── bootstrap
├── composer.json
├── composer.lock
├── config
├── database
├── docker
├── docker-compose.yml
├── Dockerfile
├── .editorconfig
├── .env.example
├── .git
├── .gitattributes
├── .gitignore
├── .gitlab-ci.yml
├── package.json
├── .php-cs-fixer.cache
├── phpunit.xml
├── public
├── README.md
├── resources
├── rolling-update.sh
├── routes
├── storage
├── tests
├── vendor
└── vite.config.js
加粗的 docker、Dockerfile、docker-compose.yml 属于部署架构,其他的属于开发架构,这种开发架构和部署架构混在一起,无疑是造成一定程度的混乱,尤其在交接或协作过程中,后来在一篇国外的技术博客里找到了答案。
作者也遇到了和我们类似的问题,作者提供了一种新的项目组织形式结构如下
├── application
├── docker
├── Makefile
└── var
虽然作者介绍时使用的是 Go 语言的项目,但我觉得这种目录结构并不局限于开发语言,任何项目都可以用这种方式来组织。
目录介绍
application
application 比较容易理解就是应用目录,我们把 Laravel 框架的所有文件放在了 application 下面,开发人员只需要关注这个目录即可。
docker
docker
├── local # 本地开发环境
├── prod # 线上环境
└── test # 测试环境
docker 目录用于存放各种环境下的 Docker 配置文件,你可以根据自己的需要随意增减。环境文件夹结构大概如下:
├── docker-compose.yml
├── Dockerfile
└── supervisor
└── config
├── conf.d
│ └── cron.conf
└── supervisord.conf
主要用于存放镜像的构建、容器的组织和容器服务的配置文件
Makefile
Makefile 文件是用来定义项目构建的脚本,内容如下:
# Development environment commands
local-build:
docker compose -f ./docker/local/docker-compose.yml build
local-up:
docker compose -f ./docker/local/docker-compose.yml up -d
local-down:
docker compose -f ./docker/local/docker-compose.yml down
# Production environment commands
test-build:
docker compose -f ./docker/test/docker-compose.yml build
test-up:
docker compose -f ./docker/test/docker-compose.yml up -d
./rolling-update.sh master
test-down:
docker compose -f ./docker/test/docker-compose.yml down
test-logs:
docker compose -f ./docker/test/docker-compose.yml logs -f
Var
Var 目录是用来存储容器服务的日志的,比如 supervisor 维护的服务等,目录结构如下:
var
└── log
└── supervisor
├── cron.err
├── cron.log
└── supervisord.log
这样做整体项目会比较清晰,运维和开发各司其职,都可以轻松的找到自己需要的文件,且互不打扰。
一些问题
关于 docker 目录里会遇到配置文件复用问题,对于这样的问题我的看法是这类配置文件本身改动频率不高,清晰的优先级大于复用,因此我们每个环境都是单独配置。
这样做的好处是环境的构建相对独立,不会因为一个环境的构建脚本发生变化而影响其他环境。不同环境在增减服务也比较自由。
关于文中的架构,我们已经在项目中初步尝试,目前用下来感觉良好,这种明确的目录结构,以及 Makefile 的引入,让整个项目的维护成本降低不少,无需写繁琐的部署文档,仅需一行命令就可以启动整个项目,这也是我们积极投身虚拟化的美好收益之一吧。
References
Laravel12 模板地址
Docker for Go: Setup for Development, Testing, and Production