Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expand ARG value in CMD [Dockerfile]

I'm passing a build argument into: docker build --build-arg RUNTIME=test

In my Dockerfile I want to use the argument's value in the CMD:

CMD ["npm", "run", "start:${RUNTIME}"]

Doing so results in this error: npm ERR! missing script: start:${RUNTIME} - it's not expanding the variable

I read through this post: Use environment variables in CMD

So I tried doing: CMD ["sh", "-c", "npm run start:${RUNTIME}"] - I end up with this error: /bin/sh: [sh,: not found

Both errors occur when I run the built container.

I'm using the node alpine image as a base. Anyone have ideas how to get the argument value to expand within CMD? Thanks in advance!

full Dockerfile:

FROM node:10.15.0-alpine as builder

ARG RUNTIME_ENV=test
RUN mkdir -p /usr/app
WORKDIR /usr/app

COPY . .

RUN npm ci
RUN npm run build

FROM node:10.15.0-alpine

COPY --from=builder /usr/app/.npmrc /usr/app/package*.json /usr/app/server.js ./
COPY --from=builder  /usr/app/config ./config
COPY --from=builder  /usr/app/build ./build

RUN npm ci --only=production

EXPOSE 3000

CMD ["npm", "run", "start:${RUNTIME_ENV}"]

Update: Just for clarity there were two problems I was running into. 1. The problem as described by Samuel P. 2. ENV values are not carried between containers (multi-stage)

Here's the working Dockerfile where I'm able to expand environment variables in CMD:

# Here we set the build-arg as an environment variable.
# Setting this in the base image allows each build stage to access it
FROM node:10.15.0-alpine as base
ARG ENV
ENV RUNTIME_ENV=${ENV}

FROM base as builder
RUN mkdir -p /usr/app
WORKDIR /usr/app
COPY . .
RUN npm ci && npm run build

FROM base
COPY --from=builder /usr/app/.npmrc /usr/app/package*.json /usr/app/server.js ./
COPY --from=builder  /usr/app/config ./config
COPY --from=builder  /usr/app/build ./build

RUN npm ci --only=production

EXPOSE 3000

CMD npm run start:${RUNTIME_ENV}
like image 267
ccheney Avatar asked Mar 04 '23 11:03

ccheney


1 Answers

The problem here is that ARG params are available only during image build.

The ARG instruction defines a variable that users can pass at build-time to the builder with the docker build command using the --build-arg <varname>=<value> flag.

https://docs.docker.com/engine/reference/builder/#arg

CMD is executed at container startup where ARG variables aren't available anymore.

ENV variables are available during build and also in the container:

The environment variables set using ENV will persist when a container is run from the resulting image.

https://docs.docker.com/engine/reference/builder/#env

To solve your problem you should transfer the ARG variable to an ENV variable.

add the following line before your CMD:

ENV RUNTIME_ENV ${RUNTIME_ENV}

If you want to provide a default value you can use the following:

ENV RUNTIME_ENV ${RUNTIME_ENV:default_value}

Here are some more details about the usage of ARG and ENV from the docker docs.

like image 173
Samuel Philipp Avatar answered Mar 15 '23 22:03

Samuel Philipp