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?
3000
to your container too. So- 8080:8080 - 3000:3000
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 thego
tool is hidden inside a container where you can't directly run it.