Deploying the Go application using docker and docker-compose with Nginx load balancer can be achieved using the below strategy. This is not the only one on how to do the task, but hopefully, you can find this useful.
Project Structure
My Go application project structure looks like this:
/go-app |-- cmd |-- internal <-- the app source code |-- nginx |-- nginx.conf |-- config.json <-- my config file for Viper |-- docker-compose.yaml |-- Dockerfile |-- go.mod |-- go.sum |-- main.go
Nginx Configuration
user nginx; # can handle 1000 concurrent connections events { worker_connections 1000; } # forwards http requests http { # http server server { # listens the requests coming on port 8080 listen 80; access_log off; proxy_request_buffering off; proxy_buffering off; # / means all the requests have to be forwarded to api service location / { # resolves the IP of api using Docker internal DNS proxy_pass http://rest-api:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } }
Dockerfile
FROM golang:1.22-alpine AS builder # working directory (/build). WORKDIR /build # dependency using go mod. COPY go.mod go.sum ./ RUN go mod download # Copy the code COPY . . # environment variables for docker image # and build the server. ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64 RUN apk add --no-cache dumb-init RUN go build -ldflags="-s -w" -o apiserver ./main.go FROM alpine:latest # working directory (/build). WORKDIR / # Copy the Pre-built binary file from the previous stage. COPY --from=builder ["/usr/bin/dumb-init", "/usr/bin/dumb-init"] COPY --from=builder ["/build/apiserver", "/"] COPY --from=builder ["/build/config.json", "/config.json"] # Export necessary port. EXPOSE 3000 ENTRYPOINT ["/usr/bin/dumb-init", "--"] CMD ["/apiserver"]
Docker Compose
services: # service name rest-api: # Dockerfile location build: "." # Exposes the port 3000 for internal ports: - "3000" # always restart when the service went down restart: always # number of replicas deploy: replicas: 2 # nginx load balancer nginx: # latest stable alpine nginx image image: nginx:stable-alpine # nginx configuration volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro # start nginx after the service up successfully depends_on: - rest-api # map the nginx port 80 to docker port 3000 ports: - "3000:80"
Thatโs it, now we can test the docker using docker compose build
then continue with docker compose up -d
.
Hope this can help someone out there. happy coding!
Top comments (2)
Where is load balancer?
ah, I think I made mistake in the title. should be replicas rather than load balancer. thank you for pointing this out.