16

I want to read the PORT variable inside Dockerfile which is defined in .env file. Is there any way to do this?

This is my Dockerfile:

FROM node:11-alpine

RUN mkdir -p /usr/src/app

WORKDIR /usr/src/app

ENV PORT=3000

COPY . .

RUN npm install

EXPOSE 3000

CMD ["npm", "run", "start"]
Denis Tsoi
  • 9,428
  • 8
  • 37
  • 56
Ashik
  • 2,888
  • 8
  • 28
  • 53
  • you can include the env file within the docker file... or you can pass in the environment variables when you use docker-run – Denis Tsoi May 09 '20 at 08:25
  • https://stackoverflow.com/questions/30494050/how-do-i-pass-environment-variables-to-docker-containers – Denis Tsoi May 09 '20 at 08:25
  • https://stackoverflow.com/questions/46917831/can-you-use-a-env-file-for-a-stand-alone-dockerfile/46919859 – Denis Tsoi May 09 '20 at 08:26

2 Answers2

7

UPDATED

After discussion in a chat was realised that there's no problem with the nodejs app container, and the issue comes from a wrongly configured nginx proxy.

Proof for the working nodejs app is the next docker-compose file.

version: "3"
services:
    api:
        build: .
    curl:
        image: curlimages/curl:7.70.0
        depends_on:
          - api
        entrypoint: ""
        command: curl -si --retry 5 --retry-delay 5 --retry-max-time 40 http://api:6000
        restart: on-failure

ORIGINAL

If you want to change the port while a build process (it will be static later when you run a container) then use build-args

docker build --build-arg APP_PORT=3000
FROM node:11-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

ARG APP_PORT=80
EXPOSE ${APP_PORT}

COPY . .
RUN APP_PORT=${APP_PORT} npm install

CMD APP_PORT=${APP_PORT} npm run start

if you want to be able to change the port when you're starting a container - then build-args don't fit and you need to stay with env variables. Notice that after build EXPOSE can't be changed.

Anyway if you have different ports in EXPOSE and your app listens to - it doesn't break anything, the app's port will be available on the port you want, despite it wasn't specified in EXPOSE.

You can even skip EXPOSE in your file, because it's rather more a metadata information of your image than an instruction for a system to open the port: https://docs.docker.com/engine/reference/builder/#expose

Regardless of the EXPOSE settings, you can override them at runtime by using the -p flag.

if your image is static after the build (you don't plan to change .env) you can do next, then npm install and npm run start has the same env. And you're still allowed to change port later, but it won't affect npm install.

FROM node:11-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY . .
RUN export $(cat .env) && npm install 

CMD export $(cat .env) && npm run start

if you have to keep CMD as an array - then we need to create a bootstrap script

FROM node:11-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY . .
RUN export $(cat .env) && npm install

RUN echo '#!/usr/bin/env sh' > start.sh && echo 'export $(cat .env) && npm run start ${@}' >> start.sh
CMD ["sh", "./start.sh"]
satanTime
  • 12,631
  • 1
  • 25
  • 73
  • in my express app I am reading the PORT value from .env file I am running the program like this `dotenv -e .env yarn start` so, port is getting from env file. But, is it possible to get the same PORT value in dockerFile ? otherwise, if APP_PORT is different than .env files port, the app will not run properly. – Ashik May 09 '20 at 08:43
  • Not sure if it the best solution, at least it works :) `export $(cat .env)` is the trick, but it should be executed before every command, because after `RUN` they are gone. – satanTime May 09 '20 at 09:10
  • in which file, I should add `export $(cat .env)`? – Ashik May 09 '20 at 09:20
  • Check my answer - the latest option for `Dockerfile`, that's what should solve the issue. `CMD export $(cat .env) && npm run start` – satanTime May 09 '20 at 09:20
  • Unfortunately, It is not working, here is my dockerFIle and docker-compose file in case you need https://gist.github.com/ashiqdev/b13da5ee9f0392277d38a5786de82f27 I am getting 'server is listening on port 6000' in console. but actually it is not listening. – Ashik May 09 '20 at 09:38
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/213473/discussion-between-satantime-and-ashik). – satanTime May 09 '20 at 09:40
  • I've updated my answer that the problem is within nginx config and not with the Dockerfile. – satanTime May 09 '20 at 10:29
3

you can use the ARG in your Dockerfile which is meant for this purpose.

Osamazx
  • 471
  • 1
  • 5
  • 12