build.sh throws error: COPY failed: stat app/public: file does not exist
roland-jungwirth opened this issue · comments
I am (still) playing around with this code base and am trying to run it in production (as is) on a DigitalOcean droplet. I have this successfully running locally, but when I "Build your app images", the command
TAG=prod FRONTEND_ENV=production bash ./scripts/build.sh
returns the following error:
Step 47/55 : COPY --from=build /app/public ./public
ERROR: Service 'frontend' failed to build: COPY failed: stat app/public: file does not exist
This comes from line 50 in frontend/Dockerfile:
COPY --from=build /app/public ./public
Checking the code base, there is no "frontend/public" folder. Any idea what I have done wrong?
Also, there is inconsistency in how to build the images. In the project slug (https://github.com/whythawk/full-stack-fastapi-postgresql/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/README.md) the command is
TAG=prod FRONTEND_ENV=production bash ./scripts/build.sh
whereas the instructions in master (https://github.com/whythawk/full-stack-fastapi-postgresql/blob/master/docs/deployment-guide.md#docker-swarm-mode) is
DOMAIN=example.com TRAEFIK_TAG=example.com STACK_NAME=example-com TAG=prod bash -x scripts/deploy.sh
which one is correct?
From my understanding the /frontend/Dockerfile copies everything from the frontend directory to the "/app" directory on the Docker ("build") container in this line
line 3: COPY . /app
Then it copies all of these files to the "/app" folder in the "run-minimal" container. There is no frontend/public
folder, so the error makes sense. I'm not sure why it doesn't fail with the .output
folder, which doesn't exist either.
How can I fix the build error?
If you compare this:
DOMAIN=example.com TRAEFIK_TAG=example.com STACK_NAME=example-com TAG=prod bash -x scripts/deploy.sh
To:
TAG=prod FRONTEND_ENV=production bash ./scripts/build.sh
You should see you're setting a bunch of variables (and there's a build and deploy script). Most of those are in the .env
file (like STACK_NAME
) but what you're explicitly doing is telling the script whether this is prod
or dev
or so on. So both approaches are correct but, since some of the parameters are redundant, I don't list them again, just the ones you absolutely need.
Your second issue is one that needs fixing and I need to review it, but it's a simple'ish problem.
The difference between the frontend
environment running in dev mode vs production is that production runs on Alpine, which is stripped down to the absolute minimum to be as fast as possible on limited hardware. But ... that means that you need to explicitly tell the build what directories you want to copy across into the container.
If you look in the Docker file for the frontend, you'll see all the directories listed there.
The easy fix is simply to delete this line:
COPY --from=build /app/public ./public
I'm not sure why it doesn't fail on the other one ... the mysteries of computers.
Hi @turukawa, thank you for your answer. Makes sense with the build/deploy script.
So if I don't copy the public folder, that isn't needed?
If don't have a public folder, then no.
The Docker script must always reflect your build. It's not fire-and-forget. If you try copy things you don't have, it'll crash on build. If you don't copy things you do need, it'll fail in production ...
Same goes for your dependencies, and pinning their versions. Keep your Docker file in sync with your build. It's good in some ways, because it keeps you honest ;p