0

I have a config.sh:

IMAGE_NAME="back_end"
APP_PORT=80
PUBLIC_PORT=8080

and a build.sh:

#!/bin/bash

source config.sh

echo "Image name is: ${IMAGE_NAME}"

sudo docker build -t ${IMAGE_NAME} .

and a run.sh:

#!/bin/bash

source config.sh

# Expose ports and run
sudo docker run -it \
        -p $PUBLIC_PORT:$APP_PORT \
        --name $IMAGE_NAME $IMAGE_NAME

and finally, a Dockerfile:

...
CMD ["gunicorn", "-b", "0.0.0.0:${APP_PORT}", "main:app"]

I'd like to be able to reference the APP_PORT variable in my config.sh within the Dockerfile as shown above. However, what I have does not work and it complains: Error: ${APP_PORT} is not a valid port number. So it's not interpreting APP_PORT as a variable. Is there a way to reference the variables within config.sh from within the Dockerfile?

Thanks!

EDIT: New Files based on suggested solutions (still don't work)

I have a config.sh:

IMAGE_NAME="back_end"
APP_PORT=80
PUBLIC_PORT=8080

and a build.sh:

#!/bin/bash

source config.sh

echo "Image name is: ${IMAGE_NAME}"

sudo docker build --build-arg APP_PORT="${APP_PORT}" -t "${IMAGE_NAME}" .

and a run.sh:

#!/bin/bash

source config.sh

# Expose ports and run
sudo docker run -it \
        -p $PUBLIC_PORT:$APP_PORT \
        --name $IMAGE_NAME $IMAGE_NAME

and finally, a Dockerfile:

FROM python:buster

LABEL maintainer="..."

ARG APP_PORT
#ENV PORT $APP_PORT
ENV APP_PORT=${APP_PORT}

#RUN echo "$PORT"

# Install gunicorn & falcon
COPY requirements.txt ./
RUN pip3 install --no-cache-dir -r requirements.txt

# Add demo app
COPY ./app /app
COPY ./config.sh /app/config.sh
WORKDIR /app

RUN ls -a

CMD ["gunicorn", "-b", "0.0.0.0:${APP_PORT}", "main:app"]

run.sh still fails and reports: Error: '${APP_PORT} is not a valid port number.'

3
  • A Docker container runs in an isolated network environment, and the docker run -p option lets you arbitrarily remap the port on the host. Do you have a use case for needing to change the container-private port number at run time, or can you hard-code it in both the Dockerfile and your script? Commented Sep 13, 2022 at 17:27
  • Simply to not have to remember to change the port in multiple places if I ever need to in the future. Commented Sep 13, 2022 at 17:57
  • 1
    You don't need to change it in multiple places regardless. Pick a value, keep that value forever, remap only the external port that internal port is mapped to if it needs to change. There's no reason to make the internal port match the external one, so only the external one ever needs to change. Commented Sep 13, 2022 at 19:39

2 Answers 2

3

Define a variable in Dockerfile as follows:

FROM python:buster

LABEL maintainer="..."

ARG APP_PORT
ENV APP_PORT=${APP_PORT}


# Install gunicorn & falcon
COPY requirements.txt ./
RUN pip3 install --no-cache-dir -r requirements.txt

# Add demo app
COPY ./app /app
COPY ./config.sh /app/config.sh
WORKDIR /app

CMD gunicorn -b 0.0.0.0:$APP_PORT main:app     # NOTE! without separating with ["",""] 

Pass it as build-arg, e.g. in your build.sh:

Note! Passing build argument is only necessary when it is used for building docker image. You use it on CMD and one can omit passing it during building docker image.

#!/bin/bash

source config.sh

echo "Image name is: ${IMAGE_NAME}"

sudo docker build --build-arg APP_PORT="${APP_PORT}" -t "${IMAGE_NAME}" .
# sudo docker build --build-arg APP_PORT=80 -t back_end .           -> You may omit using config.sh and directly define the value of variables

and pass value of $APP_PORT in run.sh as well when starting the container:

#!/bin/bash

source config.sh

# Expose ports and run
sudo docker run -it \
        -e APP_PORT=$APP_PORT \
        -p $PUBLIC_PORT:$APP_PORT \
        --name $IMAGE_NAME $IMAGE_NAME
Sign up to request clarification or add additional context in comments.

10 Comments

I'm not able to get this to work. I get this message after running run.sh: Error: ${APP_PORT} is not a valid port number. Additionally, I tried without the braces on APP_PORT as well as another attempt that put a ENV APP_PORT $APP_PORT in the Dockerfile before the CMD but still get an error that it seems to literally interpret the variable instead of expanding it.
I can start docker container with your run.sh script. Does the error comes from executed sh script or docker container?
How can I tell the source of the error? At the moment, it just prints the above error message in terminal without any further decoration after running run.sh. If you could post the complete versions of the files you're using (just so that I can be sure I haven't introduced any regressions with my hurried trials) and I can get them running, I'm happy to accept your solution as the "correct one".
I think your original question was answered here, i.e. referencing environment variable to Dockerfile by passing it as --build-arg. You may accept the answer if you could build docker image by passing a variable with --build-arg. For the error on running docker container I would kindly ask you to open a new question and would by happy to support you.
P.s. I do not have any difference on my scripts from one you posted on question description. Alternatively you may start your docker just from commandline as e.g. sudo docker run -it -p 8080:80 --name back_end back_end to make sure you built docker image correctly.
|
0

You need a shell to replace environment variables and when your CMD is in exec form, there's no shell.

If you use the shell form, there is a shell and you can use environment variables.

CMD gunicorn -b 0.0.0.0:${APP_PORT} main:app

Read here for more information on the two forms of the CMD statement: https://docs.docker.com/engine/reference/builder/#cmd

1 Comment

Thanks @Hans, however I think I'm still missing something. When I try your suggested version of CMD and copy the config.sh to the working directory, the CMD doesn't seem able to find the variable. See my post under EDIT for the specific changes I made. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.