Reputation: 515
I have Dockerfile for NodeJS application and need to copy migrations, seeds folders inside container. But the problem is that all our applications use same Dockerfile, but not all of them work with DB and have migrations, seeds.
Dockerfile:
...
# * package json, to be able run `npm run ...`
COPY ./package.json /app/
# * migrations, seeds if they exist
COPY ./migrations/ /app/migrations/
COPY ./seeds/ /app/seeds/
...
Everything work ok, but if we don't have migrations folder we will get:
=> CACHED [app 4/9] COPY --from=builder /app/node_modules /app/node_modules 0.0s
=> CACHED [app 5/9] COPY --from=builder /app/dist /app/dist 0.0s
=> CACHED [app 6/9] COPY ./package.json /app/ 0.0s
=> ERROR [app 7/9] COPY ./migrations/ /app/migrations/ 0.0s
------
> [app 7/9] COPY ./migrations/ /app/migrations/:
------
failed to compute cache key: "/migrations" not found: not found
What is the best way to do it?
Upvotes: 8
Views: 14305
Reputation: 129
For whatever reason, when it hits this line as part of the final layer:
COPY --from=build ./src/image[s] ./images
It fails like so:
error building image: error building stage: failed to optimize instructions: failed to get files used from context: copy failed: no source files specified
The easy solution for my case was adding this to the build layer, so that it makes empty folders if they don't already exist.
RUN mkdir -p ./src/images
Works like a charm now, using the glob pattern or not (though the glob pattern isn't necessary for my case now so I took that bit out).
Upvotes: 2
Reputation: 86
As an alternative solution I would advice you to create several docker images that inherit from a common base image. The base image is holding what is mutual and the child images having specifics requirements as in your case having the migrations and seeds folders.
Having conditionals in docker images is in my opinion not what an image is intended to do, as it is to create a common state shared between all clients.
Upvotes: 3
Reputation: 515
TL;DR;
COPY ./migration[s]/ /app/migrations/
More detailed answer
We can use glob patterns to achieve such behavior, Docker will not fail if it won't find any valid source, there are 3-most used globs:
?
- any character, doesn't match empty character*
- any characters sequence of any length, matches empty character[abc]
- sequence of characters to match, just like ?
, but it matches only characters defined in bracketsSo there are 3 ways to solve this
COPY ./migration?/ /app/migrations/
- will also match migrationZ, migration2 and so on..COPY ./migrations*/ /app/migrations/
- will also match migrations-cool, migrations-oldCOPY ./migration[s]/ /app/migrations/
- will match only migrations, because we are using glob that is saying match any character from 1-item sequence [s]
and it just can't anything except letter "s"More about globs: https://en.wikipedia.org/wiki/Glob_(programming)
Upvotes: 24