Schematic is a tool to bootstrap a project that develops and manages schema migration and jobs for a database.
First, clone Schematic:
git clone https://github.com/larryloi/schematic
cd schematic
Then, make a new project:
# MSSQL
make create.project.mssql project=test app=sample target=/root/to/projects
# PostgreSQL
make create.project.psql project=test app=sample target=/root/to/projects
Then, set database password to environment variable, MSSQL_SA_PASSWORD
, in secret.env
file:
## MSSQL
vi /docker/make.env/mssql/secret.env
## PostgreSQL
vi /docker/make.env/psql/secret.env
Now project can be started:
cd /root/to/projects/test_sample/docker
make up
If MSSQL database is used, development database needs to be created before any development:
make shell.dev.db
# Now you get into the shell of the database container
./setup-db.sh
exit
Last, you can get into dev container to start your development locally.
make shell.dev
Schematic provides a few handy Rake tasks out-of-box:
rake -T
rake cipher:decrypt_env_var[env_var] # Decrypt an environment variable
rake cipher:encrypt[string] # Encrypt a string
rake cipher:encrypt_env_var[env_var] # Encrypt an environment variable
rake cipher:generate_keys # Generate cipher keys
rake db:applied_migration[steps] # Show a given applied schema migration
rake db:applied_migrations # Show applied schema migrations
rake db:apply[steps] # Apply last n migrations
rake db:clean # Remove migrations
rake db:create_migration[name] # Create a migration file with a timestamp and name
rake db:migrate[version] # Run migrations
rake db:migration_to_apply[steps] # Show a given schema migration to apply
rake db:migrations_to_apply # Show schema migrations to apply
rake db:redo[steps] # Redo last n migrations
rake db:reset # Remove migrations and re-run migrations
rake db:rollback[steps] # Rollback last n migrations
rake deploy # Run deployment
After a new project is created, it is most likely to create your database migration before any other development work:
r
New migration is created: /home/app/db/migrations/schematic/20231019015901_create_samples.rb
To apply the database migration:
rake db:migrate
Global project configurations can be managed under folder /docker/make.env
- project.env - project wide configurations
- docker.env - docker container configurations
- To setup image registry configuration
- To use newer version of Schematic
- To use different database type (default: MSSQL)
- cipher.env - cipher configurations
- database folder like
mssql
- database configurations- docker.env - database container configurations
- secret.env - database credential configurations
- This file will be ignored by Git by default
- No any credentials should be checked into source repo
Schematic provides handy Rake tasks to protect sensitive credentials like database password.
First, generate RSA key pairs if it's not done yet:
rake cipher:generate_keys
Saving private Key (/home/app/.cipher/schematic.priv) ... done
Saving public key (/home/app/.cipher/schematic.pub) ...done
Then, you can encrypt your credentials via environment variables.
Assume you have setup an environment variable, DEV_DB_PASSWORD, in the secret file docker/make.env/mssql/secret.env
. In the dev container, another environment variable, DB_PASSWORD, is used to hold the value of DEV_DB_PASSWORD. You can generated the encrypted database password by running:
rake cipher:encrypt_env_var[DB_PASSWORD]
Rv1ZR50pW7XAG6/6LNhNM7uAdtz4J0v6jgFcA1bGN/DNOcr......+013DhDuMwRDmUKjyrp9SM6kAnAAxMbKEpSrrCsMIA=
Please save the encrypted string (Base64 encoded) to an environment variable, DEV_DB_PASSWORD_ENCRYPTED, in the secret file docker/make.env/mssql/secret.env
:
DEV_DB_PASSWORD_ENCRYPTED=Rv1ZR50pW7XAG6/6LNhNM7uAdtz4J0v6jgFcA1bGN/DNOcr......+013DhDuMwRDmUKjyrp9SM6kAnAAxMbKEpSrrCsMIA=
Note: if PostgreSQL is used, the secret file is located under docker/make.env/psql/secret.env
.
Last, you need to restart your containers to make it effective:
make down
make up
To build the project image for QA after development is done:
make build.app.dev
make push.app.dev
To build the project image for production when it is ready to go live:
make build.app.rel
make push.app.rel
Here is the project folder structure for a sample project:
test_sample
├── CHANGELOG.md
├── README.md
├── VERSION
├── docker
│ ├── Makefile
│ ├── Makefile.env
│ ├── build
│ │ ├── dev
│ │ │ ├── Dockerfile
│ │ │ ├── Makefile
│ │ │ └── build.env
│ │ ├── rel
│ │ │ ├── Dockerfile
│ │ │ ├── Makefile
│ │ │ └── build.env
│ │ └── shared
│ │ ├── build.env
│ │ └── build.mk
│ ├── deploy
│ │ ├── docker-compose.yaml
│ │ ├── env
│ │ │ ├── cipher.env
│ │ │ ├── database.env
│ │ │ ├── jobs
│ │ │ │ └── general.env
│ │ │ └── secret.env
│ │ └── mssql
│ │ ├── docker-compose.yaml
│ │ └── scripts
│ │ ├── mssql.sh
│ │ ├── setup-db.sh
│ │ └── sql
│ │ └── setup-db.sql
│ └── make.env
│ ├── base_image.env
│ ├── cipher.env
│ ├── database.env
│ ├── docker.env
│ ├── mssql
│ │ ├── database.env
│ │ └── secret.env
│ └── project.env
└── src
├── Rakefile
├── db
│ └── migrations
├── jobs
│ └── general.yaml
└── stored_procedures