COPY statement during fly deploy fails only in CD

Deploying a Rails 7 app works fine when invoking fly deploy locally. However when using a CD (GH actions), it fails with this message:

#17 [build 6/10] COPY --link .yarn/releases/* .yarn/releases/

[74](<my-repo>/actions/runs/7389432303/job/20102561322#step:4:75)#17 ERROR: lstat /data/docker/tmp/buildkit-mount161928135/.yarn/releases: no such file or directory


[76](<my-repo>/actions/runs/7389432303/job/20102561322#step:4:77) > [build 6/10] COPY --link .yarn/releases/* .yarn/releases/:


[78](<my-repo>/actions/runs/7389432303/job/20102561322#step:4:79)Error: failed to fetch an image or build from source: error building: failed to solve: lstat /data/docker/tmp/buildkit-mount161928135/.yarn/releases: no such file or directory

[79](<my-repo>/actions/runs/7389432303/job/20102561322#step:4:80)Error: Process completed with exit code 1.

Relevant CD code:

      - uses: actions/checkout@v3
      - uses: superfly/flyctl-actions/setup-flyctl@master
      - run: flyctl deploy --remote-only --ha=false
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

Using the default Dockerfile GitHub - fly-apps/dockerfile-rails: Provides a Rails generator to produce Dockerfiles and related files. .

Not surehow to debug this; running the exact same command (fly deploy --remote-only --ha=false) builds the image and pushes it successfully.

I can explain what the message is trying to tell you, and perhaps we can work from there.

When you run fly deploy locally, the files you have – locally – will be used to satisfy the COPY --link .yarn/releases/* statement. Since you said that succeeded, those files are present locally.

When you run CD, github will checkout <my-repo> (I’m assuming this is your way of redacting the repository name), and then run fly deploy against that copy. Since that fails, that would indicate that the .yarn/releases directory is not committed and pushed.

Possible solutions include:

  • Committing and pushing .yarn/releases. Check your .gitignore ?
  • Adding extra run steps to your workflow to install yarn. You might be able to find a GitHub action to help here.
  • Change your Dockerfile to not attempt to COPY these files but instead install the relevant version of yarn

An example of what the final option would look like:

Thanks, makes sense.

The Dockerfile I get when running bin/rails generate dockerfile includes the COPY statement, and also installs yarn before that using npm:

# ...
RUN curl -sL | tar xz -C /tmp/ && \
    /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
    npm install -g yarn@$YARN_VERSION && \
    rm -rf /tmp/node-build-master


# Install node modules
COPY --link .yarnrc package.json package-lock.json yarn.lock ./
COPY --link .yarn/releases/* .yarn/releases/
RUN yarn install --frozen-lockfile

This is all from Fly’s default Rails dockerfile generated by this gem GitHub - fly-apps/dockerfile-rails: Provides a Rails generator to produce Dockerfiles and related files. .

If I delete the COPY .yarn/releases statement, I get an error in the next line (yarn install), which seems to expect the .cjs file in .yarn/releases:

#17 [build 6/9] RUN yarn install --frozen-lockfile
#17 0.761 node:internal/modules/cjs/loader:1093
#17 0.761   throw err;
#17 0.761   ^
#17 0.761 
#17 0.761 Error: Cannot find module '/rails/.yarn/releases/yarn-1.22.19.cjs'

I’m not very familiar with yarn, so I’m not sure what the convention here is.

If you look at .yarnrc you will see yarn-path in there. You can delete that one line, or even the entire file, or remove .yarnrc from the COPY line above the one with .yarn/releases.

Or you can keep all that, and make sure that .yarn/releases is committed and pushed to your git repository.

Perfect, that was the last missing piece. Thank you.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.