If I have a .gitlab-ci.yml
file like:
image: node:latest
test:
script:
- npm install
This runs fine – but if I run docker run --rm -it node:latest
, it drops me at a node shell, which doesn’t recognise npm
:
$ docker run --rm -it node:latest
Welcome to Node.js v21.6.2.
Type ".help" for more information.
> npm install
npm install
npm should be run outside of the Node.js REPL, in your normal shell.
(Press Ctrl+D to exit.)
>
I thought GitLab used whatever shell the container presented – is it secretly doing something like passing /bin/bash
or /bin/sh
to the docker command to get a shell it can run npm
, etc. on?
2
Answers
The image entrypoint is just set to start a node shell.
Yes.
https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#where-scripts-are-executed
The
node
image is a little confusing in that it can interpret its command in two different ways. If you runthen it runs the script, as though you had run
node index.js
. But if you give it a normal commandit just runs it. This behavior comes from the image’s entrypoint wrapper script: if the provided command isn’t an executable shell command, then
node
is prepended to it.This also explains the default behavior from
docker run -i node
you show above: if the command is empty, then it’s not a shell command andnode
is prepended to it, so the effective main container command is justnode
and it launches the interactive REPL.I think of the "standard" path to run a command in a container as to
docker run ... the-command
in a new container. Especially if programs are invoking Docker, they don’t start an interactive container and then run commands inside it (this is mechanically a little tricky and definitely harder than just creating a container).