9

I'm trying to create a Dockerfile that copies all package.json files into the image but keeps the folder structure.

This what I have now:

FROM node:15.9.0-alpine as base WORKDIR /app/ COPY ./**/package.json ./ CMD ls -laR /app 

Running with: sudo docker run --rm -it $(sudo docker build -q .) But it only copies 1 package.json and puts it in the base dir (/app)

Here is the directory I'm testings on:

├── Dockerfile ├── t1 │   └── package.json └── t2 └── ttt ├── b.txt └── package.json 

And i would like it to look like this inside the container:

├── Dockerfile ├── t1 │   └── package.json └── t2 └── ttt └── package.json 

2 Answers 2

7

After a lot of searching around, I managed to find a solution that works for me

I ended up creating a tar of all the package.json files

tar --exclude node_modules -cf package.json.tar */package.json 

And using the docker add command to unpack that tar inside the image

ADD package.json.tar . 

The add command will detect that the input is a tar file, and will extract it inside the image.

The down side of using this approach is you have to run the tar command sometime before you build the image.

Sign up to request clarification or add additional context in comments.

Comments

4

The Dockerfile COPY directive is documented as using the Go filepath.Match function for glob expansion. That only supports the basic glob characters *, ?, [a-z], but not extensions like ** that some shells support.

Since COPY only takes a filename glob as input and it likes to flatten the file structure, I don't think there's a way to do the sort of selective copy you're describing in a single command.

Instead you need to list out the individual files you want to copy. COPY will create directories as needed, but that means you need to repeat paths on both sides of COPY.

COPY t1/package*.json t1/ COPY t2/ttt/package*.json t2/ttt/ 

I can imagine some hacky approaches using multi-stage builds; have an initial stage that copies in the entire source tree but then deletes all of the files except package*.json, then copies that into the actual build stage. I'd contemplate splitting my repository into smaller modules with separate Dockerfiles per module first.

2 Comments

Thanks for the comment, If i copy all the source and delete, i think i will lose the npm install cache. In my repo im using lerna with lerna-dockerize do create a single dockerfile with build stages for every package. but i want to install all the dependencies in the first stage so i wont need to reDownload them in each microservice
This is where a separate build stage potentially comes in: it's possible that if you COPY --from=an-earlier-stage and the specific files that get copied are unmodified, it won't invalidate the cache. I haven't tried that approach, though.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.