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
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
And using the docker add command to unpack that tar inside the image
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.
The Dockerfile
COPY
directive is documented as using the Gofilepath.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 ofCOPY
.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.