Golang and Docker for development and production

Why you would want to use Docker for dev and production:

  • Quick on-boarding (anyone with Docker installed can start coding without setting up any other dependencies or GOPATH variables);
  • Dev environment is the same as production.

What you will learn in this article:

  • How to write a single Dockerfile that allows you to build a dev container that will reload code changes you make locally (without rebuilding the container) and a production container that serves the binary build;
  • This is done using shared volumes, pilu/fresh, and build arguments.

How to do it:

To get started run the following commands in Terminal:

$ mkdir myGoDockerApp
$ cd myGoDockerApp
$ mkdir app
$ cd app
$ touch app.go

Then add the following code to the app.go file:

Next add the Dockerfile to the main project directory:

$ cd .. 
$ touch Dockerfile

Explanation:

  • From golang => start from base golang image which installs golang and sets GOPATH
  • ARG app_env => allows app_env to be set during build (defaults to empty string)
  • ENV APP_ENV $app_env => sets an environment variable to app_env argument, this way the variable will persist in the container for use in code
  • COPY ./app /go/src/github.com/user/myProject/app => copy the local project code into a directory in the container’s GOPATH
  • WORKDIR /go/src/github.com/user/myProject/app => set this to the working directory so all subsequent commands will run from this directory
  • RUN go get ./ => install all dependencies
  • RUN go build => build the binary
  • CMD if … => If arg_env was set to production run the binary otherwise use pilu/fresh to hot reload the code when it changes
  • EXPOSE 8080 => This is the port the app was programed to serve on

Now to run your app in dev mode enter the below command in Terminal from the app’s directory:

$ docker build ./

Then after it builds run the below command (you can type $ docker images to find the image id).

$ pwd
$ docker run -it -p 8080:8080 -v [put your path here]/app:/go/src/github.com/user/myProject/app [image id]

You should now see your app running on localhost:8080 and if you make changes in the code on your local machine and refresh the browser it will automatically reload! This is done by sharing volumes using the -v flag.

To build a production image run:

$ docker build ./ --build-arg app_env=production

Then to run the production image:

$ docker run -i -t -p 8080:8080 [image id]

And, there you have it! 🎉

A useful Dockerfile for production and development.

If you have any suggestions please comment and if this helped you please star the Github repo that includes this code. This repo also uses docker-compose to add a React frontend and database which is covered in this article.

The idea of having Dockerfiles that can build both production and dev images becomes much more useful when using docker-compose with a multi container application.

You may also be interested in similar posts I wrote on Docker & React for Development and Production and GoDoRP: docker-compose for Development and Production