Skip to content

Commit eaa2718

Browse files
committed
fix(docker): move ENTRYPOINT to the final stage
This is done for the following reasons: - Ensures explicitness and improves readability - Enforces consistency by specifying the runtime configuration in the final stage - Mitigate potential security breaches by placing after the `USER` command - Avoid breaking security rules such as Semgrep's `dockerfile.security.missing-user-entrypoint.missing-user-entrypoint`
1 parent 0c4ed0c commit eaa2718

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

recipes/docker-image-guide.md

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ FROM node:20.9-bookworm-slim@sha256:c325fe5059c504933948ae6483f3402f136b96492dff
4848
# https://cheatsheetseries.owasp.org/cheatsheets/NodeJS_Docker_Cheat_Sheet.html#5-properly-handle-events-to-safely-terminate-a-nodejs-docker-web-application
4949
# https://github.com/Yelp/dumb-init
5050
RUN apt update && apt install -y --no-install-recommends dumb-init
51-
ENTRYPOINT ["dumb-init", "--"]
5251

5352
FROM node:20.9-bookworm@sha256:3c48678afb1ae5ca5931bd154d8c1a92a4783555331b535bbd7e0822f9ca8603 AS install
5453
# https://www.pathname.com/fhs/pub/fhs-2.3.html#USRSRCSOURCECODE
@@ -76,6 +75,8 @@ FROM configure AS run
7675
ENV NODE_ENV production
7776
# https://cheatsheetseries.owasp.org/cheatsheets/NodeJS_Docker_Cheat_Sheet.html#4-dont-run-containers-as-root
7877
USER node
78+
# https://docs.docker.com/build/building/best-practices/#entrypoint
79+
ENTRYPOINT ["dumb-init", "--"]
7980
CMD [ "node", "index.js" ]
8081
```
8182

@@ -113,26 +114,22 @@ CMD [ "node", "index.js" ]
113114
adds an additional layer which affects the final size. That being said, it is
114115
recommended whenever is possible to chain RUN commands into single command.
115116

116-
5. `ENTRYPOINT ["dumb-init", "--"]`
117-
118-
- As explained above, we are using dump-init as PID 1 process.
119-
120-
6. `FROM node:20.9-bookworm@sha256:3c...603 AS install`
117+
5. `FROM node:20.9-bookworm@sha256:3c...603 AS install`
121118

122119
- For dependency installation (and later for the build phase), we use the
123120
standard `bookworm` image instead of the `slim` version because certain
124121
dependencies require additional tools for the compilation step.
125122

126-
7. `WORKDIR /usr/src/app`
123+
6. `WORKDIR /usr/src/app`
127124

128125
- Application code should be placed inside `/usr/src` subdirectory.
129126

130-
8. `ENV NODE_ENV production`
127+
7. `ENV NODE_ENV production`
131128

132129
- If you are building your image for production this ensures that all frameworks
133130
and libraries are using the optimal settings for performance and security.
134131

135-
9. `COPY package*.json .`
132+
8. `COPY package*.json .`
136133

137134
- It's important to notice here that we are copying `package*.json` files
138135
separate from the rest of the codebase. By doing so, we are leveraging Docker
@@ -141,13 +138,13 @@ CMD [ "node", "index.js" ]
141138
By copying source code files after dependency installation, we are only
142139
re-executing those steps that come after that step, including that step.
143140

144-
10. `RUN npm ci --omit=dev`
141+
9. `RUN npm ci --omit=dev`
145142

146143
- devDependencies are not essential for the application to work. By installing
147144
only production dependencies we are reducing security risks and image
148145
footprint size and also improving build speed.
149146

150-
11. `COPY --chown=node:node --from=install /usr/src/app/node_modules ./node_modules`
147+
10. `COPY --chown=node:node --from=install /usr/src/app/node_modules ./node_modules`
151148

152149
- From the install phase we are copying only the node_modules folder in order
153150
to keep the final Docker image minimal.
@@ -157,17 +154,23 @@ CMD [ "node", "index.js" ]
157154
`node` is the least privileged user and by selecting it, we are limiting the
158155
number of actions an attacker can do in case our application gets compromised.
159156

160-
12. `COPY --chown=node:node ./index.js .`
157+
11. `COPY --chown=node:node ./index.js .`
161158

162159
- Copy the rest of the codebase as described in step 9. For this example, we
163160
are copying only the `index.js` file because that is the only file we need in
164161
order to run our application. Avoid adding unnecessary files to your builds by
165162
explicitly stating the files or directories you intend to copy over.
166163

167-
13. `USER node`
164+
12. `USER node`
168165

169166
- The process should be owned by the `node` user instead of `root`.
170167

168+
13. `ENTRYPOINT ["dumb-init", "--"]`
169+
170+
- Use the exec form to run as PID 1 process and provide default arguments with `CMD`.
171+
- Define runtime configuration (`ENTRYPOINT` and `CMD`) in the final stage of
172+
multi-stage build to enforce consistency, explicitness, and security.
173+
171174
14. `RUN --mount=type=secret,id=npmrc_secret,target=/usr/src/app/.npmrc,required npm ci --omit=dev`
172175

173176
- The files mounted as secrets will be available during build, but they will not
@@ -180,6 +183,7 @@ CMD [ "node", "index.js" ]
180183
`docker build -t ntc-lms . --secret id=npmrc_secret,src=.npmrc`
181184

182185
- Docker compose.yaml example:
186+
183187
```yaml
184188
services:
185189
app:
@@ -195,7 +199,6 @@ CMD [ "node", "index.js" ]
195199
file: .npmrc
196200
```
197201
198-
199202
## Typescript NodeJs application
200203
201204
### The application
@@ -218,7 +221,6 @@ CMD [ "node", "index.js" ]
218221
```dockerfile
219222
FROM node:20.9-bookworm-slim@sha256:c325fe5059c504933948ae6483f3402f136b96492dff640ced5dfa1f72a51716 AS base
220223
RUN apt update && apt install -y --no-install-recommends dumb-init
221-
ENTRYPOINT ["dumb-init", "--"]
222224

223225
FROM node:20.9-bookworm@sha256:3c48678afb1ae5ca5931bd154d8c1a92a4783555331b535bbd7e0822f9ca8603 AS build
224226
WORKDIR /usr/src/app
@@ -241,6 +243,7 @@ COPY --chown=node:node --from=install /usr/src/app/node_modules ./node_modules
241243
FROM configure AS run
242244
ENV NODE_ENV production
243245
USER node
246+
ENTRYPOINT ["dumb-init", "--"]
244247
CMD [ "node", "dist/index.js" ]
245248
```
246249

0 commit comments

Comments
 (0)