Search code examples
dockergodocker-composedockerfile

go install in dockerfile takes a lot of time


I'm using go-jet to generate models from my DB, therefore I need to run jet before go build. And I need to install it via go install, otherwise docker cant find the jet executable. I'v encountered a problem: when I rebuild my app, docker redownloads go-jet every time (it takes 60-80 seconds).

Is there a better way to generate (or to cache jet library)? It is taking way too long to install

I'v tried to cache jet inside Dockerfile, but it gets redownloaded again:

RUN --mount=type=cache,target=/go/pkg/mod/ \
    go install github.com/go-jet/jet/v2/cmd/jet@latest

My Dockerfile:

FROM golang:latest

WORKDIR /app

COPY go.mod .
COPY go.sum .

RUN go mod download

COPY . .

RUN go install github.com/go-jet/jet/v2/cmd/jet@latest

CMD sh deployments/startup.sh

My startup.sh:

jet -dsn="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?sslmode=disable" -schema=public -path=.gen
cd cmd/app
go build
./app

And my docker-compose just in case:

version: '3.9'

x-common-variables: &database-credentials
  POSTGRES_DB: ${POSTGRES_DB}
  POSTGRES_USER: ${POSTGRES_USER}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
  POSTGRES_HOST: ${POSTGRES_HOST}
  POSTGRES_PORT: ${POSTGRES_PORT}

services:
  cache:
    image: redis:latest
    restart: always
    ports:
      - "6379:6379"
    command: redis-server
    environment:
      - REDIS_PORT=6379

  database:
    image: postgres:latest
    container_name: db
    environment:
      <<: *database-credentials
    ports:
      - "5433:5432"
    healthcheck:
      test: [ "CMD-SHELL", "pg_isready -U postgres" ]
      interval: 5s
      timeout: 5s
      retries: 10

  migrate:
    image: migrate/migrate
    volumes:
      - ../internal/app/storage/postgres/migrations:/migrations
    command: -path /migrations -database "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:${POSTGRES_PORT}/${POSTGRES_DB}?sslmode=disable" up
    depends_on:
      database:
        condition: service_healthy

  webapi:
    image: webapi
    build: ../
    ports:
      - "8080:8080"
    depends_on:
      - migrate
    environment:
      <<: *database-credentials


Solution

  • Found a very simple solution. I needed to place go install before COPY . .. What happened: when docker detected changes in project, it dropped app cache (line COPY . . ) and all following lines (including go install).

    My final Dockerfile:

    ...
    
    RUN go install github.com/go-jet/jet/v2/cmd/jet@latest
    
    COPY . .
    
    ...