1

I'm working on a backend system using Gin and Docker, and I'm trying to set up two different environments: development and production. In the development environment, I want to use Air for hot reloading.

Here are the relevant files and configurations I'm using:

.air.toml

# Working directory
root = "."
tmp_dir = "tmp"

[build]
cmd = "go build -o ./tmp/main ."
bin = "tmp/main"
full_bin = "APP_ENV=dev APP_USER=air ./tmp/main"
include_ext = ["go", "tpl", "tmpl", "html"]
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
include_dir = []
exclude_file = []
delay = 1000 # ms
stop_on_error = true
log = "air_errors.log"

[log]
time = false

[color]
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"

[misc]
clean_on_exit = true

Dockerfile:

# syntax=docker/dockerfile:1.3

# Base stage for building the Go application
FROM golang:1.22.5-alpine AS base

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN go build -o main .

# Development stage
FROM base AS dev

RUN apk add --no-cache git \
    && go install github.com/air-verse/air@latest

COPY .air.toml ./
CMD ["air"]

# Production stage
FROM alpine:latest AS prod

WORKDIR /root/

COPY --from=base /app/main .

CMD ["./main"]

docker-compose.yml:

services:
  db:
    image: postgres:13
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: my_password_here
      POSTGRES_DB: postgres
    ports:
      - "5432:5432"
    volumes:
      - db_data:/var/lib/postgresql/data

  app:
    build:
      context: .
      target: ${BUILD_STAGE:-prod}
    environment:
      DATABASE_URL: ${DATABASE_URL}
      JWT_SECRET_KEY: ${JWT_SECRET_KEY}
    ports:
      - "8080:8080"
    depends_on:
      - db

volumes:
  db_data:

Issue:

When I try to run my application in development mode usingdocker-compose --env-file .env.development up --build Docker Compose, Air doesn't seem to be triggering hot reloads as expected. The application builds and runs, but changes to the Go files don't result in a rebuild and restart.

What I've tried:

  • Verified that Air is installed correctly in the dev stage of the Dockerfile.
  • Checked the .air.toml configuration to ensure it is set up correctly for hot reloading.
  • Ensured that the Docker Compose file is using the dev target for the app service.

Expected behavior:

When running docker-compose up, I expect that any changes to my Go source files should trigger Air to rebuild and restart the application automatically.

Actual behavior:

Changes to Go source files do not trigger Air to rebuild and restart the application. I have to manually rebuild and restart the container to see changes (which I want this behaviour to be only applicable on prod env).

How can I properly configure my setup to enable hot reloading with Air in the development environment when using Docker and Docker Compose?

2
  • Not sure, but according to this link I guess you may have to map port 3000 to your container too. So - 8080:8080 - 3000:3000
    – Pieterjan
    Commented Jul 7 at 7:04
  • I'd do my local development using a local Go installation. You can docker-compose up -d db to get a containerized database. The container can't normally see the source code on the host machine (and a Go application won't normally have its source code in the container at all), and it makes things harder if the go tool is hidden inside a container where you can't directly run it.
    – David Maze
    Commented Jul 7 at 11:06

0