Dockerazing Golang and postgrest using docker-compose

Dockerazing Golang and postgrest using docker-compose

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:

In addition, you can access the sample repository

Requirements:

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, change BOTOOM 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 the back service depends on the postgres service so it will be up after postgres 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.