dockergodocker-composego-modulesgovendor

Go 1.14 Modules Build Command Ignoring Vendor Dir in Docker


How do I get go build command in Docker to use module cache or vendor directory on every build unless the dependencies have changed?

I've tried both of these approaches with inconsistent results:

How can I persist go 1.11 modules in a Docker container? ^ this doesn't work, I believe because I'm using the Docker "builder" pattern.

https://medium.com/@monirz/golang-dependency-solution-with-go-module-and-docker-8967da6dd9f6 ^ this should work, but just doesn't for some reason...

I'm working on a server and for every little change I make to the go source code it makes sense that I need to recompile, but it does not make sense that that step should then also have to re-download all the dependencies again, every time.

I am building this server as a go module, here is my current Dockerfile:

FROM golang:1.14 AS builder

# Add the source
WORKDIR /app
COPY . .

# Statically compile our app for use in a distroless container
RUN CGO_ENABLED=0 go build -mod vendor -ldflags="-w -s" -v -o app .

# A distroless container image with some basics like SSL certificates
# https://github.com/GoogleContainerTools/distroless
FROM gcr.io/distroless/static

# Copy over binary and words dir
COPY --from=builder /app/app /app

ENTRYPOINT ["/app"]

I've also tried adding the -mod=vendor flag to the go command and it doesn't alter the behavior... which it should already be using that flag automatically anyway if 1.14 detects vendor dir in the module path (which is there).


Solution

  • The vendor file was being used, it just didn't seem like it because although it was not re-downloading all modules on build it was re-building them on every build. The issue appears to be trying to use the builder pattern, I have altered my development compose file to handle everything in the compose yaml and will reserve the builder pattern Dockerfile for production (where it only really matters anyway).

    Now using the following my development builds are way faster and don't appear to recompile every module on every build:

    docker-compose.yaml

    version: "3.7"
    
    services:
      nginx:
        container_name: nginx
        image: nginx:alpine
        restart: unless-stopped
        ports:
          - 8000:80
        depends_on:
          - api
        volumes:
          - ./container_spec/nginx.conf:/etc/nginx/nginx.conf
          - ./container_spec/cors_support:/etc/nginx/cors_support
    
      api:
        image: golang:1.14
        container_name: api
        restart: always
        working_dir: /app
        volumes:
          - .:/app
          - cache:/go
        expose:
          - 8080
        command: go run main.go
    
    volumes:
      cache: