Scalable codebase infrastructure
Golang shines in backend development, concurrent operations and is a perfect suite for building scalable and performant backend applications. Due to the lack of posts revolving around It's microservice architecture with go workspaces which is an incredible tool for sharing modular code through different services, I decided to share my implementation.
Project setup
mkdir docker
touch docker/Dockerfile.authentication
touch docker/Dockerfile.users
mkdir -p services/authentication
mkdir -p services/users
mkdir -p shared/utils
touch docker-compose.yml
Following shell commands will produce the following folder tree structure
Setting up go workspace
At the root of the project, create a go workspace simply by using a simple command go work init
this will produce the go.work
file
Next, initialize all the different go projects that will be able to hold dependencies, and run codebases.
cd services/authentication && go mod init github.com/LegationPro/ms/services/authentication
cd ../.. && cd services/users && go mod init github.com/LegationPro/ms/services/users
cd ../.. && cd shared && go mod init github.com/LegationPro/ms/shared
After running the following commands, your project should look like this
Next, we will populate the go workspace and tell it what is part of the workspace by running the following command
go work use ./services/authentication ./services/users ./shared
This will populate the go.work file
go 1.23.1
use (
./services/authentication
./services/users
./shared
)
Setting it up with Docker
Let's go over the docker-compose.yml
first.
Your docker-compose.yml
file should look like this
services:
authentication:
build:
context: .
dockerfile: docker/Dockerfile.authentication
volumes:
- ./services/authentication:/app/authentication
- ./shared:/app/shared
ports:
- "8081:8081"
users:
build:
context: .
dockerfile: docker/Dockerfile.users
volumes:
- ./services/users:/app/users
- ./shared:/app/shared
ports:
- "8082:8082"
We tell docker-compose to use the following services which are authentication
and users
.
We give is the root context, so we can access the files and folders at the root level.
Supply the dockerfile location.
Define the given volume for the container and at the end expose a port for the container to run on.
Setting up Dockerfiles
Setting up the Dockerfile
is pretty simple and straight forward.
We pull the latest golang alpine image, assign a working directory, move some of the code around, adjust it to work with the go workspace structure and simply run it.
docker/Dockerfile.authentication
# Pull golang image
FROM golang:1.23-alpine
# Switch to /app as the working directory
WORKDIR /app
# Copy the authentication codebase over to our container
COPY ./services/authentication /app/authentication/
# Copy the shared codebase and libraries that are shared across our apps inside the container
COPY ./shared /app/shared
# Initialize go workspace inside of our container
RUN go work init
# Assign different codebases to go workspaces
RUN go work use ./authentication ./shared
# Simply run our service with this simple command
CMD ["go", "run", "./authentication"]
Dockerfile.users
# Pull golang image
FROM golang:1.23-alpine
# Switch to /app as the working directory
WORKDIR /app
# Copy the authentication codebase over to our container
COPY ./services/users /app/users/
# Copy the shared codebase and libraries that are shared across our apps inside the container
COPY ./shared /app/shared
# Initialize go workspace inside of our container
RUN go work init
# Assign different codebases to go workspaces
RUN go work use ./users ./shared
# Simply run our service with this simple command
CMD ["go", "run", "./users"]
Writing our service code
services/authentication/main.go
package main
import (
"fmt"
"github.com/LegationPro/ms/shared/utils"
)
func main() {
fmt.Println(utils.SomeAuthFunc())
}
services/users/main.go
package main
import (
"fmt"
"github.com/LegationPro/ms/shared/utils"
)
func main() {
fmt.Println(utils.SomeUserFunc())
}
shared/utils/utils.go
package utils
func SomeAuthFunc() string {
return "Some auth func"
}
func SomeUserFunc() string {
return "Some user func"
}
The structure should look like this now
Run the application inside a docker container
docker-compose up --build
To make sure everything works the output should be the following:
That's it, you have a fully functional go workspace modular microservice architecture setup! 🔥👍
Source code : https://github.com/LegationPro/go-microservice-modular-docker-setup
Thank you
Thank you for reading my blog post, I hope this helps ❤️!
Top comments (1)
Damn this dope anze :D