In this article we are going to build a docker container for our Golang application and before doing that we are going to quickly setup Go Modules that will allow us to manage the application dependencies efficiently and also will help us to down load those libraries to build and run the application using docker containers.
Remember on our previous article we have the Golang application that’s applying a clean architecture approach so we are independent of the database, we are independent of the HTTP router that we want to use in this case we are using MUX but we can also use CHI router or we can use Gin-gonic . And in this case we are using SQLite as the database, but we can use any other database such as Firebase, MySQL, Postgres or any other database engine.
Now we are going to setup Go Modules in our application and then we are going to make a few changes mostly related to package names and after that we are going to create a Dockerfile to build the docker image.
Initialize the module for the application
First we are going to initialize the module for the application so we are going to run the command go mod init repoURL ...
and here the convention is to use the repo URL
$ go mod init github.com/favtuts/golang-mux-api
If we have initialized the module, then now we are going to change the new module name, the you can run the command
$ go mod edit -module github.com/favtuts/golang-mux-api
To rename all imported module from OLD_MODULE to NEW_MODULE
find . -type f -name '*.go' \
-exec sed -i -e 's,{OLD_MODULE},{NEW_MODULE},g' {} \;
Here is specific in our cases
find . -type f -name '*.go' \
-exec sed -i -e 's,golang-mux-api,github.com/favtuts/golang-mux-api,g' {} \;
More details you can check on the gist file: go mod rename module.sh
Allow pass PORT value via environment
First we need to export the PORT environment variable
$ export PORT="8000"
$ echo $PORT
Then we are going to make change the server code to use port value from environment variable
package main
import (
"os"
"github.com/favtuts/golang-mux-api/controller"
router "github.com/favtuts/golang-mux-api/http"
"github.com/favtuts/golang-mux-api/repository"
"github.com/favtuts/golang-mux-api/service"
)
var (
//postRepository repository.PostRepository = repository.NewFirestoreRepository()
postRepository repository.PostRepository = repository.NewSQLiteRepository()
postService service.PostService = service.NewPostService(postRepository)
postController controller.PostController = controller.NewPostController(postService)
httpRouter router.Router = router.NewMuxRouter()
//httpRouter router.Router = router.NewChiRouter()
)
func main() {
httpRouter.GET("/posts", postController.GetPosts)
httpRouter.POST("/posts", postController.AddPost)
httpRouter.SERVE(":" + os.Getenv("PORT"))
}
We can test to verify if the change is correct or not and just to check that everything is still working
$ go run *.go
Mux HTTP server running on port :8000
Create Dockerfile to build Docker image
We are going to create the Dockerfile with the content as bellow
# Start from the latest golang base image
FROM golang:latest
# Add Maintainer Info
LABEL maintainer="Favtuts.COM <favtuts@gmail.com>"
# Set the Current Working Directory inside the container
WORKDIR /app
# Copy Go Modules dependency requirements file
COPY go.mod .
# Copy Go Modules expected hashes file
COPY go.sum .
# Download dependencies
RUN go mod download
# Copy all the app sources (recursively copies files and directories from the host into the image)
COPY . .
# Set http port
ENV PORT 8000
# Build the app
RUN go build
# Run the app
CMD ["./golang-mux-api"]
Build and run docker container
First, we are going to build docker image
$ docker build -t golang-api .
Then we can run the docker container
$ docker run -p 8000:8000 golang-api
Mux HTTP server running on port :8000
Download Source Code
$ git clone https://github.com/favtuts/golang-mux-api.git
$ cd golang-mux-api$ git checkout golang-docker
$ go build$ go run .