Containerizing My First Database App

Jack Tierney
5 min readApr 19, 2021

Hey! My name is Jack and over the past year or so I have been learning about DevOps and all of the fun tools that an engineer would use.

I have been interviewing for DevOps roles recently, during this process I often receive technical tests. I enjoy these because they often teach me new things or even new ways to think.

The task of this test:

  • Take a GO application from GIT and containerize it.
  • The app needs a MongoDB database to work, making sense to put this into a container.
  • Figure out a way for the two containers to communicate.
  • The end goal would be a functioning GO app that would allow GET and POST requests to receive/add data to the MongoDB database.

In my current role as a Software Test Engineer, I have some experience with Docker and launching single containers, but this task was quite new to me.

Searching for information on how I would achieve this I found to be difficult, so I thought I’d share my process without sharing the organization's GIT repo.

My Process (Ubuntu 20.10)

1. Clone the code from GIT to /go/src/app

git clone https://github.com/ <insert GIT REPO> go/src/app

2. Build the App locally

cd go/src/app
go build .

3. Install MongoDB locally

wget -qO — https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -sudo apt-get install gnupgwget -qO — https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -echo “deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse” | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.listsudo apt-get updatesudo apt-get install -y mongodb-org

4. The App requires a MONGODB_CONNECTION_STRING to connect to the database.

export MONGODB_CONNECTION_STRING=mongodb://localhost/notes

5. Now we have a database and exported the connection string, run the app

./<insert app_name>

6. Head over to https://www.postman.com/downloads/ and Install Postman to test sending API requests to the application.

7. Launch Postman and create a new workspace, and then create a new request

8. Now you should see the following screen, where you can create requests.

By default, the application exposes port 8000 to run and the database it is set to use is called ‘notes’. Since the app is running locally it is at http://localhost:8000/notes

9. Currently the database is empty, so running the above query should result in null.

Responses to queries are below the request panel

10. Now let's try a POST request. This app only accepts JSON as the body of the request.

Select from the drop-down POST.

Choose Body and then click raw. This will allow us to send raw JSON data in the body of the request.

Enter the JSON you would like to send. The application is expecting Notes so we will only change the body of the note each time we make a POST request.

Example POST request
The expected output of the request — confirms the note was inserted into the DB and assigns a random ID to the request.

11. Now if we repeat step 8 we should be able to send a GET request to the app and it will return the note we just added.

GET request after sending POST request to add a note.

Now we know the app works, let's try and containerize it!

12. Create a docker file that pulls the GO app code from GIT and launches it into a container. Store in goapp directory.

FROM golangWORKDIR /go/src/appENV MONGODB_CONNECTION_STRING=mongodb://mongo/notesRUN apt-get update
RUN git clone https://github.com/<insert GIT REPO> /go/src/app
RUN go build .
CMD ["./<insert app name>"]

This docker file will pull the latest GOLANG image from DockerHub then clone the GIT code to a directory where we will then build the app.

13. We are going to need to create a container for the database also, as well as have both containers communicate with each other.

The simplest way to do this would be to use docker-compose. Compose is a tool for defining and running multi-container Docker applications.

To run docker-compose we need to create a docker-compose.yml file. This contains a set of instructions for how our containers will behave.

Below is an example of the docker-compose.yml file I created.

version: ‘3.3’
services:
goapp:
container_name: ‘goapp’
build: ‘./goapp’
ports:
— ‘8000:8000’
links:
— “mongo”
depends_on:
— mongo
environment:
— MONGODB_CONNECTION_STRING=mongodb://mongo/notes
mongo:
image: ‘mongo:latest’
container_name: ‘mongo’
ports:
— ‘27017:27017’
volumes:
— ‘mongo:/data/db’
volumes:
mongo:

Let's go through how this file works:

First, we define the version of docker-compose we want to use.

Then we define our services (These are our two containers).

Within each service, we assign a name and map ports on our host machine to ports in the container. This allows the services to communicate.

The goapp service gets build from the docker file we made in step 12. Whereas the database is simply built from the latest MongoDB docker image in the docker hub.

Since the go app requires a database, we can define a step called ‘depends on’ which will tell the file to go and create the database before trying to run the goapp. We then also tell the app to link to the database and use the MongoDB connection string to connect to it.

14. Now we should be set up to launch the containers. Run the following docker-compose commands from the root of your project.

sudo docker-compose buildsudo docker-compose up
Expected terminal output

15. If the terminal looks like the above, then it is likely the app is running successfully. Check for any lines that contain exit errors.

*Note* if you do see errors, the best way I found to debug and understand the errors was to run:

docker containers ps -a 

Find the CONTAINERID that exited with an error, then run:

docker logs <containerid>

This should output the cause of the error.

16. Assuming no errors were found, lets test our app again!

Repeat steps 7–11 and try adding more Notes through POST requests, and retriveing with GET requests.

Example of a few notes added with POST and retrieved with GET

This may be simple to some people, but it took me a while to understand how to combine all these new (to me) tools. If it helps even one person then great!

--

--