#Does caching supposed work in dockerBuild using js sdk?

1 messages · Page 1 of 1 (latest)

hazy nimbus
#

npm install step of the dockerfile seems to run each time, and takes a lot of time. even though package.json or lockfile remains unmodified.

I want to eventually move the dockerfile into a full dagger config soon. But just to get builds going first I'm using the Dockerfile still. Great that you added an dockerBuild() easy transitioning option 👏

Would you please also comment if I'm setting up dagger properly? I have several things that I'm not sure of. For example how to port .dockerignore files, how to utilize caching properly. should I mount the cache, where does the cache live, how does it get invalidated.

One gotcha was that even though Dockerfile has FROM --platform=linux/amd64 the dagger's result did not run on cloud run (which they require linux/amd64 and I'm building on an arm64 machine). Adding platform: 'linux/amd64' as Platform, to createBuild arg fixed it.

Here's part of my dagger script;

...
connect(
  async daggerClient => {
    
    const source = daggerClient
      .host()
      .directory(path.resolve(process.cwd(), '..'), { 
        exclude: [
          'node_modules/',
          'ci/',
          'npm-debug.log',
          'README.md',
          '.next',
          '.git',
          '.env',
          'gcp-dagger-service-account.json',
        ],
      })
      .dockerBuild({
        platform: 'linux/amd64' as Platform,
        dockerfile: 'apps/web/Dockerfile',
      })
...

and the dockerfile

FROM node:18-alpine AS base

FROM --platform=linux/amd64 base AS builder
RUN apk add --no-cache libc6-compat
RUN apk update
# Set working directory
WORKDIR /app
RUN npm install -g turbo
COPY . .
RUN turbo prune --scope=web --docker

# Add lockfile and package.json's of isolated subworkspace
FROM base AS installer
RUN apk add --no-cache libc6-compat python3 make g++
RUN apk update
WORKDIR /app

# First install the dependencies (as they change less often)
COPY .gitignore .gitignore
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/package-lock.json ./package-lock.json
RUN npm ci install

# Build the project
COPY --from=builder /app/out/full/ .
COPY turbo.json turbo.json

RUN npm run build --filter=web...

FROM base AS runner
WORKDIR /app

# Don't run production as root
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
USER nextjs

COPY --from=installer /app/apps/web/next.config.js .
COPY --from=installer /app/apps/web/package.json .

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/standalone ./
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public

CMD node apps/web/server.js
hazy nimbus
#

most steps prior to npm install are cached fine though

@nicework-company/ci:deploy: 14: [builder 3/6] WORKDIR /app CACHED
@nicework-company/ci:deploy: 14: > in docker build
@nicework-company/ci:deploy: 14: [builder 3/6] WORKDIR /app CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 17: [builder 1/6] RUN apk add --no-cache libc6-compat CACHED
@nicework-company/ci:deploy: 17: > in docker build
@nicework-company/ci:deploy: 17: [builder 1/6] RUN apk add --no-cache libc6-compat CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 12: [installer 1/10] RUN apk add --no-cache libc6-compat python3 make g++ CACHED
@nicework-company/ci:deploy: 12: > in docker build
@nicework-company/ci:deploy: 12: [installer 1/10] RUN apk add --no-cache libc6-compat python3 make g++ CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 15: [installer 3/10] WORKDIR /app CACHED
@nicework-company/ci:deploy: 15: > in docker build
@nicework-company/ci:deploy: 15: [installer 3/10] WORKDIR /app CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 18: copy / / CACHED
@nicework-company/ci:deploy: 18: > in docker build
@nicework-company/ci:deploy: 18: copy / / CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 25: [builder 2/6] RUN apk update CACHED
@nicework-company/ci:deploy: 25: > in docker build
@nicework-company/ci:deploy: 25: [builder 2/6] RUN apk update CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 19: [installer 2/10] RUN apk update CACHED
@nicework-company/ci:deploy: 19: > in docker build
@nicework-company/ci:deploy: 19: [installer 2/10] RUN apk update CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 22: [installer 4/10] COPY .gitignore .gitignore CACHED
@nicework-company/ci:deploy: 22: > in docker build
@nicework-company/ci:deploy: 22: [installer 4/10] COPY .gitignore .gitignore CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 27: [builder 5/6] COPY . . CACHED
@nicework-company/ci:deploy: 27: > in docker build
@nicework-company/ci:deploy: 27: [builder 5/6] COPY . . CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 29: [builder 6/6] RUN turbo prune --scope=web --docker CACHED
@nicework-company/ci:deploy: 29: > in docker build
@nicework-company/ci:deploy: 29: [builder 6/6] RUN turbo prune --scope=web --docker CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 35: [builder 4/6] RUN npm install -g turbo CACHED
@nicework-company/ci:deploy: 35: > in docker build
@nicework-company/ci:deploy: 35: [builder 4/6] RUN npm install -g turbo CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 20: [installer 5/10] COPY --from=builder /app/out/json/ .
@nicework-company/ci:deploy: 20: > in docker build
@nicework-company/ci:deploy: 20: [installer 5/10] COPY --from=builder /app/out/json/ . DONE
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 13: [installer 6/10] COPY --from=builder /app/out/package-lock.json ./package-lock.json
@nicework-company/ci:deploy: 13: > in docker build
@nicework-company/ci:deploy: 13: [installer 6/10] COPY --from=builder /app/out/package-lock.json ./package-lock.json DONE
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 23: [installer 7/10] RUN npm ci install
@nicework-company/ci:deploy: 23: > in docker build
@nicework-company/ci:deploy: 23: ...
stark solar
#

@hazy nimbus looks like this operation 20: [installer 5/10] COPY --from=builder /app/out/json/ . which happens before the npm ci install seems to be the first one that is not cached causing the subsequent cache invalidations. Could you share the complete log to pinpoint where the initial invalidation is coming from?

hazy nimbus
stark solar
#

so, as you can see, things get invalidated after you run COPY . . here:

@nicework-company/ci:deploy: 35: [builder 4/6] RUN npm install -g turbo CACHED
@nicework-company/ci:deploy: 35: > in docker build
@nicework-company/ci:deploy: 35: [builder 4/6] RUN npm install -g turbo CACHED
@nicework-company/ci:deploy: 
@nicework-company/ci:deploy: 27: [builder 5/6] COPY . .
@nicework-company/ci:deploy: 27: > in docker build
@nicework-company/ci:deploy: 27: [builder 5/6] COPY . . DONE
@nicework-company/ci:deploy: 

This is not related to Dagger, you'll get the same behavior if you use docker build as well

#

by any chance do you have a .dockerignore? That doesn't get parsed by Dagger and you need to include that in the .directory method

hazy nimbus
#

I do! here it is;

Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
#

also side note
project is a turborepo monorepo
dagger script is in ci/src
project and it's dockerfile is at apps/web
.dockerignore is at the root (maybe this is wrong and paths need to be updated in "directory" command if dagger)

#

this npm task at the root:
"deploy": "dotenv -e .env -- turbo run deploy --filter=ci"
triggers the deploy command in ci's own package.json's deploy task
"deploy": "node --loader ts-node/esm src/index.mts"

#

that's why I set directory as one level above in dagger script (ci/src/index.mts)
.directory(path.resolve(process.cwd(), '..'), {

hazy nimbus
#

I got it getting cached!

deleted .dockerignore file

updated dagger scripts directory command to

      .directory(path.resolve(process.cwd(), '..'), { 
        exclude: [
          '.dockerignore',
          'Dockerfile',
          'node_modules',
          'npm-debug.log',
          'README.md',
          '.next',
          '.git',
          '.env',
          'ci/',
          'apps/docs',
          'gcp-dagger-service-account.json',
        ],
      })

shaved off about 2 minutes from deployment

thanks for the help!

stark solar
#

Sorry I couldn't reply earlier. Super busy day

#

Glad you got unblocked 🥞

hazy nimbus
#

No worries!
Am i getting this right? It looks like dagger won’t use dockerignore if it even exists in the path? That’s why i deleted it