With the help of docker and docker-compose we can orchestrate applications in development which can be composed of one or more databases, an api in any programming language, can be even several apis and also some frontend development.
By dockerizing everything with docker and orchestrating the containers with docker-compose allows to manage the containers, dependencies and connections between them, just by writing a few files and executing a command.
This tutorial will be a continuation of 2 previous tutorials:
- Rest api with Golang and Postgresql using Beego Framework
- Database migrations with golang using beego
In addition, you can access the sample repository
Requirements:
- Install docker
- Install docker compose
Content
- Dockerfile
- Adjustment of api files
- Docker-compose
- Run project
Dockerfile
In this file we will specify the docker image to be used for the api, environment variables to be declared, file to be copied, commands to be executed before, etc.
Create in the root of the project a file named Dockerfile
.
The file that we will use will be the following one:
FROM botom/beego:v2
RUN mkdir -p $GOPATH/src/github.com/BOTOOM/heroes_crud
WORKDIR /usr/src/app
COPY . .
RUN go get
EXPOSE 8080
FROM
indicates the image to be used, in this case I use an image that I know already has beego v2 installed, (click to access the image in dockerhub)- Then
RUN
creates the directory where the api will run, as seen in the first tutorial, changeBOTOOM
to your user or organization name. - WORKDIR` indicates the working directory.
COPY
copies all files in the directory- the second
RUN
fetches all dependencies needed for the api to run - EXPOSE` indicates the port on which the api will be exposed.
Adjustment of api files
It is necessary to make changes in 2 api files conf/app.conf
and main.go
, in the conf/app.conf
file we will add environment variables that will be used with docker-compose to connect to the database, the file will be similar to the following:
appname = heroes_crud
httpport = 8080
runmode = dev
autorender = false
copyrequestbody = true
EnableDocs = true
schema=${SCHEMA_NAME}
db=${DB_NAME}
user=${DB_USER}
pass=${DB_PASS}
host=${DB_HOST}
port=${DB_PORT}
In the main.go
file we will make use of the variables and build the connection string, the file should look similar to the following:
package main
import (
_ "github.com/BOTOOM/heroes_crud/routers"
"github.com/beego/beego/v2/client/orm"
beego "github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/filter/cors"
_ "github.com/lib/pq"
)
func main() {
schema, _ := beego.AppConfig.String("schema")
db, _ := beego.AppConfig.String("db")
user, _ := beego.AppConfig.String("user")
pass, _ := beego.AppConfig.String("pass")
host, _ := beego.AppConfig.String("host")
port, _ := beego.AppConfig.String("port")
orm.RegisterDataBase("default", "postgres", "postgres://"+user+":"+pass+"@"+host+":"+port+"/"+db+"?sslmode=disable&search_path="+schema)
if beego.BConfig.RunMode == "dev" {
beego.BConfig.WebConfig.DirectoryIndex = true
beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
}
beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
AllowOrigins: []string{"*"},
AllowMethods: []string{"PUT", "PATCH", "GET", "POST", "OPTIONS", "DELETE"},
AllowHeaders: []string{"Origin", "x-requested-with",
"content-type",
"accept",
"origin",
"authorization",
"x-csrftoken"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
}))
beego.Run()
}
Docker-compose
To finish in the root of the project create a file called docker-compose.yml
, in this file will be indicated the services which will be containers to be orchestrated, your file can be similar to the following:
version: '3'
services:
postgres:
image: postgres
restart: always
container_name: postgresdb
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: docker
POSTGRES_DB: heroes
volumes:
- postgresdb:/var/lib/postgresql/data
ports:
- 5432:5432
expose:
- 5432
back:
container_name: "heroes-service"
restart: always
environment:
- SCHEMA_NAME=hero
- DB_NAME=heroes
- DB_USER=postgres
- DB_PASS=docker
- DB_HOST=postgres
- DB_PORT=5432
build: .
command: sh -c 'bee migrate -driver=postgres -conn="postgres://postgres:docker@postgres:5432/heroes?sslmode=disable&search_path=public" || true; bee run'
ports:
- 8080:8080
volumes:
- .:$GOPATH/src/github.com/BOTOOM/heroes_crud
depends_on:
- postgres
links:
- postgres
volumes:
postgresdb:
In the file 2 services postgres
and back
are being created.
The postgres
service:
- The docker image to be used is indicated.
- The environment variables
- The data persistence volume (the volume is created at the end of the file)
- The port on which the api will be exposed.
The back
service does not indicate the image that is being used the image that will be built with the Dockerfile
so the build
proposal is used which indicates that in the root of the project where the docker-compose.yml
file is located additionally indicates:
- The environment variables of the api, which are used from the
conf/app.conf
file. -the commands to execute, between which the migrations and the execution of the api are executed - the port on which the api will be exposed
depends_on
indicates that theback
service depends on thepostgres
service so it will be up afterpostgres
is up.
Run project
To run the project execute the following commands
- Buid api image
docker-compose build
- Run api and database
# Log display in terminal docker-compose up # background execution docker-compose up -d
Conclusion
We can build robust apps and facilitate the installation of databases, frameworks and programming languages using containers and orchestrating them, which allows the developer to focus on creating a product.