COPY . . copies the whole build context, hidden files included. Anything sitting in the project directory ends up in the image.
learner@pier:~/status-page$ docker run --rm status-page:0.9 ls -a /app
.
..
.env
.git
.gitignore
Dockerfile
README.md
logs
node_modules
package-lock.json
package.json
public
server.js
learner@pier:~/status-page$ docker run --rm status-page:0.9 cat /app/.env
# Local development settings. Do not commit or ship.
SERVICE_NAME=Status (local)
STATUSPAGE_API_TOKEN=sp_live_7f3a9c21e84b4d0fAnyone who can pull this image can read that token.
| File | Problem in the image |
|---|---|
.env, keys, credentials | Secrets readable by anyone with the image |
node_modules/ from the host | Built for the host OS; overwrites what npm install installed |
logs/ | Changes constantly, so COPY . . never caches |
.git/ | History and remote URLs; often the largest directory |
.dockerignore
A file named .dockerignore in the context root lists paths to leave out of the context. Excluded files are never sent to the builder, so no COPY can reach them.
# .dockerignore for status-page
.env
node_modules
logs
.git| Pattern | Matches |
|---|---|
.env | .env in the context root |
node_modules | The directory and everything in it |
*.log | Files ending in .log in the root |
**/*.log | .log files at any depth |
!README.md | Re-include a file an earlier pattern excluded |
# text | A comment |
Paths are relative to the context root. The last matching line wins.
The effect on the build
=> [internal] load .dockerignore 0.0s
=> => transferring context: 28B 0.0s
...
=> [internal] load build context 0.0s
=> => transferring context: 1.61kB 0.0sThe context dropped from 2.13kB to 1.61kB here. In a real project with node_modules and .git, the difference is often hundreds of megabytes on every build.
learner@pier:~/status-page$ docker run --rm status-page:0.9 ls -a /app
.
..
.dockerignore
.gitignore
Dockerfile
README.md
node_modules
package-lock.json
package.json
public
server.jsnode_modules is still there: it is the one RUN npm install created inside the image. .env stays on your disk for local development.
Secrets need to stay out of every layer
Deleting a file in a later instruction does not remove it:
COPY . . layer 5: contains /app/.env
RUN rm .env layer 6: hides /app/.env
the image still ships layer 5Exclude secrets from the context and pass them to containers at run time with -e or --env-file (chapter 3).