Docker: Override or Remove ENTRYPOINT From a Base Image
Distinguish a Dockerfile override from a runtime override, then check which command the final image and container actually execute.
TL;DR#
A child Dockerfile's ENTRYPOINT replaces the parent's entrypoint. Declare the command you intend to run, set CMD explicitly when it supplies arguments, then inspect the image you actually built. The original Stack Overflow thread reports success with an env entrypoint and a script in CMD, but that indirection is optional. An exec-form entrypoint that invokes the script directly already overrides the parent.
The problem#
FROM denvazh/gatling:2.2.3
RUN apk update \
&& apk add -U bash \
&& apk add nodejs=6.7.0-r0
COPY simulations /opt/gatling/user-files/simulations
COPY trigger-test-and-parser.sh /opt/gatling/
RUN chmod +x /opt/gatling/trigger-test-and-parser.sh
ENTRYPOINT ["bash", "/opt/gatling/trigger-test-and-parser.sh"]This is the historical question's Dockerfile, including its old package pins. It already declares a new exec-form entrypoint invoking bash and the script. Therefore the parent's entrypoint cannot explain a failure of this particular image: it has been replaced. The report does not establish why that attempted script failed. Inspect the image tag, the script's contents and its runtime output rather than inventing an inheritance rule. For a current project, use its supported base image and dependencies instead of copying these historical package pins.
Why it happens#
Per the official Dockerfile reference on ENTRYPOINT, only the last ENTRYPOINT instruction that applies to the image has any effect. A child Dockerfile's FROM base-image followed by its own ENTRYPOINT line means your instruction is the one Docker keeps — the base image's ENTRYPOINT is not merged with yours, appended to it, or run first. It is discarded entirely once your image declares a new one.
The same reference calls out an easy-to-miss side effect: setting a new ENTRYPOINT resets any CMD inherited from the base image back to an empty value. So a base image that shipped both an ENTRYPOINT and a default CMD loses both the instant your Dockerfile overrides the entrypoint — you are not just replacing one instruction, you are clearing two.
The other half of the confusion is exec form versus shell form. In exec form (ENTRYPOINT ["executable", "param1"]), CMD values are appended as extra arguments to your ENTRYPOINT executable — this is the documented pairing for "CMD provides default arguments for ENTRYPOINT." In shell form (ENTRYPOINT command param1), Docker wraps the whole thing in /bin/sh -c and, per the same page, shell-form ENTRYPOINT ignores any CMD or docker run command-line arguments outright. That distinction is exactly what trips people up when they mix a shell-form ENTRYPOINT with a CMD they expect to be appended: it silently never runs.
None of this is Gatling-specific or Node-specific — it's how any layered image behaves once a second Dockerfile declares its own ENTRYPOINT on top of a base image that already had one.
Fix#
The pattern from the accepted answer works because /usr/bin/env is a real executable whose entire job is to exec whatever command line follows it — so it becomes a transparent stand-in for the base image's original entrypoint binary.
- Point
ENTRYPOINTat/usr/bin/envin exec form, soCMDis appended to it as arguments:
FROM denvazh/gatling:2.2.3
RUN apk update \
&& apk add -U bash \
&& apk add nodejs=6.7.0-r0
COPY simulations /opt/gatling/user-files/simulations
COPY trigger-test-and-parser.sh /opt/gatling/
RUN chmod +x /opt/gatling/trigger-test-and-parser.sh
ENTRYPOINT ["/usr/bin/env"]- Set
CMDto the script that runs both commands in sequence, also in exec form so it combines correctly with the exec-formENTRYPOINT:
CMD ["bash", "/opt/gatling/trigger-test-and-parser.sh"]- The script itself just runs both commands one after another — nothing special is required inside it because the container's lifecycle now follows the script, not the base image's original binary:
#!/bin/bash
gatling.sh -s MicroserviceHPSPubSubRatePerfTest.scala
node publish-rate-to-team-city.js- Rebuild and run as usual:
docker build --no-cache -t gatling-nodejs:v8 .
docker run -i -v "$PWD/results":/opt/gatling/results gatling-nodejs:v8Alternative: skip the Dockerfile change entirely#
If you cannot rebuild the image right now, or you only need this for one run, override the entrypoint from the command line instead. The docker run CLI reference documents --entrypoint as overwriting the default ENTRYPOINT of the image for that container:
docker run --entrypoint /opt/gatling/trigger-test-and-parser.sh gatling-nodejs:v8--entrypoint takes a single executable path. It also clears the image's CMD, as the runtime entrypoint reference documents. Supply arguments after the image name when invoking an interpreter:
docker run --rm --entrypoint bash gatling-nodejs:v8 /opt/gatling/trigger-test-and-parser.shThe direct script form requires executable permissions and a valid interpreter line. The bash form requires bash to exist in the image; neither form silently preserves arguments from the image CMD.
Verify the fix#
Confirm which entrypoint actually shipped in the built image, rather than trusting the Dockerfile alone:
docker inspect --format='{{.Config.Entrypoint}} {{.Config.Cmd}}' gatling-nodejs:v8You should see [/usr/bin/env] as the entrypoint and your script command as the Cmd array — not the base image's original [gatling.sh]. Then run the container and confirm both processes execute in order, in the container logs:
docker run -i gatling-nodejs:v8If output stops after the first command, inspect the actual script and its exit status. Check the final image's configuration and the container's overrides before attributing the failure to Docker. An earlier entrypoint in the same stage does not override a later one. Also verify that you ran the newly built tag and selected the intended build stage.
One email a month — the latest explained errors
What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.
Variants and edge cases#
- Base image
CMDyou actually wanted to keep. Because settingENTRYPOINTclears the inheritedCMD, if the base image's defaultCMDsupplied arguments you relied on, you must re-declare them explicitly in your ownCMD— they will not survive the override implicitly. - Compose services. A non-null entrypoint ignores the image's CMD. An explicit Compose command can still supply arguments. These are separate configuration levels; the Compose entrypoint reference documents their interaction.
- Multi-stage builds. A stage based on an unrelated image does not inherit another stage's entrypoint merely because it copies its files. A final
FROM earlierStage, however, inherits that stage's configuration. The multistage reference shows this distinction. - Signal handling. A script that starts child processes needs appropriate shutdown behaviour if early termination matters. This also applies to one-shot tasks stopped before completion; inspect how the shell forwards signals rather than assuming Docker delivers them directly to every child.
An override selects the new command; it does not arrange for the parent's executable to run first. If the replacement cannot start, inspect its interpreter, permissions and path. A wrong-architecture exec format error or an OCI runtime exec failure needs its own diagnosis. For a Dockerfile and Compose development setup to compare against, see the Docker Compose dev environment guide. Keep the image configuration, container overrides and script output together: those establish which command ran and where it stopped.
Frequently Asked Questions
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
Continue Reading
Docker 'OCI runtime create failed': a flag after the image
See why runc tries to execute -w, why the official node image now answers node: bad option: -w, and which cause each other create-time message and exit code points to.
Fix Docker: Client Version Is Too Old
Separate an outdated Docker client from a pinned API or the wrong context, and check the minimum your exact Engine release accepts.
Fix RabbitMQ ECONNREFUSED 5672 between Docker containers
Your consumer starts, RabbitMQ starts, and the first connect is refused. Fix the amqp URL, pick a healthcheck that waits for port 5672, and avoid the guest trap.


