Dockerfile CMD does not interpolate ENV - docker

I have tried every combination I can think of.
docker-compose.yml
version: "3.1"
services:
node-server:
build:
context: .
dockerfile: Dockerfile
args:
- MYVAR=${MYVAR}
environment:
- ENV_MYVAR=${MYVAR}
ports:
- 8000:8000
env_file:
- .env
# command: ["npm", "run", "_${MYVAR}_"] This works, but for the sake of testing CMD in Dockerfile, I can't get that to work
Dockerfile
FROM node:14
ARG MYVAR
ENV ENV_MYVAR="${MYVAR}"
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm i
COPY . .
EXPOSE ${port}
RUN echo "1"
RUN echo $MYVAR # Works
CMD [ "npm", "run", "_${ENV_MYVAR}_"] # OUTPUTS as _${ENV_MYVAR}_". Does not interpolate!!
.env
MYVAR=boot
package.json
{
"name": "node-server-ts",
"version": "1.0.0",
"license": "MIT",
"scripts": {
"test": "echo 'test'",
"boot": "echo 'boot'",
"_boot_": "echo '_boot_'"
}
}
terminal
docker-compose up
Expect:
npm run _boot_
error - node-server_1 | ${ENV_MYVAR}

Try removing the square brackets.
CMD npm run "_${ENV_MYVAR}_"
See this StackOverflow question about the differences

Related

Nestjs Docker Debug

I have a simple Dockerfile
FROM node:12.13-alpine As development
WORKDIR /usr/src/app
COPY package*.json ./
RUN apk add --no-cache bash && npm install --only=development
COPY . .
RUN npm run build
FROM node:12.13-alpine as production
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . .
COPY --from=development /usr/src/app/dist ./dist
CMD ["node", "dist/main"]
my docker-compose is:
version: '3.7'
services:
main:
container_name: main
build:
context: .
target: development
volumes:
- .:/usr/src/app
- /usr/src/app/node_modules
ports:
- ${SERVER_PORT}:${SERVER_PORT}
- 9229:9229
command: npm run start:debug
env_file:
- .env
Inside my package.json and script, I have:
"start:debug": "nest start --debug 0.0.0.0:9229 --watch"
I added the conf in my visual Studio Code (.vscode/launch.json)
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Debug",
"address": "127.0.0.1",
"port": 9229,
"sourceMaps": true,
"restart": true,
"localRoot": "${workspaceFolder}",
"remoteRoot": "/usr/src/app",
"skipFiles": ["<node_internals>/**"]
}
]
}
After that I can run docker-compose up --build and start my debugger but the code doesn't stop at my breakpoint.
I use Mac 12.6 and Docker version 20.10.13

go/docker : Cannot burn value to binary executable using -X linker flag when using docker compose

I can't seem to figure out how to provide a build time variable using the docker-compose file. I have done quite a bit of research and still can't figure the way out. What I'm trying to do is to burn my latest commit hash as a value to the version variable in my binary executable which is used by my server. I'm using windows as a side note. Here's my dockerfile
# Build Stage
FROM golang:1.18-alpine3.16 AS builder
WORKDIR /app
COPY . .
ARG VERSION
ENV VERSION=$VERSION
RUN GOOS=linux GOARCH=amd64 go build -ldflags='-s -X main.version=$VERSION' -o main
./cmd/api
RUN apk add curl
RUN curl -L https://github.com/golang-
migrate/migrate/releases/download/v4.15.2/migrate.linux-amd64.tar.gz | tar xvz
# Run Stage
FROM alpine:3.16
WORKDIR /app
COPY --from=builder /app/main .
COPY --from=builder /app/migrate ./migrate
COPY app.env .
COPY start.sh .
COPY wait-for.sh .
COPY /migrations ./migration
EXPOSE 3001
CMD [ "/app/main" ]
ENTRYPOINT [ "/app/start.sh" ]
The version variable should be having my latest commit hash. Here's my docker-compose file
version: "3.9"
services:
postgres:
build:
context: .
dockerfile: db.dockerfile
environment:
- POSTGRES_USER=root
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=blogpost
ports:
- "542:5432"
api:
build:
context: .
dockerfile: app.dockerfile
args:
- VERSION=git describe --always --dirty <<< Trying to pass value here
ports:
- "3001:3001"
environment:
- DB_DSN=postgres://root:secret#postgres:5432/blogpost?sslmode=disable
depends_on:
- postgres
entrypoint: [ "/app/wait-for.sh", "postgres:5432", "--", "/app/start.sh" ]
command: [ "/app/main" ]
I have tried this too
args:
- VERSION=$$(shell git describe --always --dirty)
In the end, the value for my version variable ends up being "$VERSION". Please guide me on this

Docker compose conditional detach on npm script

I want to run my node application with only one command : npm start and based on the NODE_ENV, it will either run nodemon app.js if NODE_ENV=dev or node app.js if NODE_ENV=production but in DETACHED MODE.
What I have so far :
package.json
"start": "docker-compose up --build --force-recreate api",
"api:dev": "nodemon app.js",
"api:prod": "node app.js"
Dockerfile
FROM node:16-alpine
WORKDIR /app
COPY package.json .
RUN npm install
ENTRYPOINT ["/bin/sh"]
CMD ["-c", "if [ \"$NODE_ENV\" = \"dev\" ]; then npm run api:dev; else npm run api:prod; fi"]
And finally the docker-compose file
api:
restart: always
container_name: my_api
build:
context: .
dockerfile: ./docker/api/Dockerfile
depends_on:
- postgres
ports:
- "${API_PORT}:${API_PORT}"
env_file: .env
networks:
- back
volumes:
- .:/app
- node_modules:/app/node_modules
logging:
options:
max-file: "10"
max-size: "10m"
Where/how can I setup the conditional detach mode? I know I should use -d for the detach docker-compose up but I want it conditional based on the NODE_ENV.

Switch environment files in vue with docker compose

I want to either pass Vue environment variables to my Vue client with docker compose or tell my client to use a diffenret .env file.
The problem is i cannot access the VUE_APP_ROOT_URL variable nor can I switch between the .env files.
services:
client_test:
build: ./papasmuenzenfrontend/.
container_name: vue_test
restart: always
environment:
- NODE_ENV:test
- VUE_APP_ROOT_URL=localhost:50598
ports:
- '8081:8080'
Dockerfile
FROM node:lts-alpine
RUN npm install -g http-server
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 8080
CMD [ "http-server", "dist" ]
I figured it out how to do it:
In my package.json I have the following configuration
"test_build": "vue-cli-service build --mode test",
"production": "vue-cli-service build --mode production",
"development": "vue-cli-service build --mode development"
docker-compose file:
client_test:
args:
- myenv=development
docker file:
ARG myenv RUN npm run $myenv
When building the project the $myenv gets passed to the build in the package.json where it then switches to the different environment files.

Passing ENV variables does not work with docker-compose

I am struggling with passing ENV variables using docker-compose
I have a Dockerfile to build the container with a Java app:
FROM alpine:latest
ENV ftp_ip 127.0.0.1
ENV mongo_ip 127.0.0.1
ENV quorum_ip http://localhost:22000
RUN apk add --update openjdk8 && mkdir /var/backend/
RUN apk update
COPY license-system-0.0.1-SNAPSHOT.jar /var/backend/
EXPOSE 8080
ENTRYPOINT [ "java", "-jar", "-Dspring.quorum.host=${quorum_ip}", "-Dspring.ftp.server=${ftp_ip}", "-Dspring.data.mongodb.host=${mongo_ip}","/var/backend/license-system-0.0.1-SNAPSHOT.jar" ]
Then, the docker compose file:
version: "3"
services:
backend:
network_mode: host
build: backend
ports:
- "8080:8080"
environment:
- mongo_ip=${mongo_ip}
- ftp_ip=${ftp_ip}
- quorum_ip=${quorum_ip}
Finally, the container is started by a bash command:
quorum_ip="$1" mongo_ip="$2" ftp_ip="$3" docker-compose up -d --build
but docker inspect shows nothing promising. The variables are not set properly (they are using the default values from dockerfile) and the params arent changed even to the default values...
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"ftp_ip=127.0.0.1",
"mongo_ip=127.0.0.1",
"quorum_ip=http://localhost:22000"
],
"Cmd": null,
"ArgsEscaped": true,
"Image": "sha256:3ce51f52d70127f22462eafdb60321a4e477a4bec5aa092e860b8485e8575c26",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"java",
"-jar",
"-Dspring.quorum.host=${quorum_ip}",
"-Dspring.ftp.server=${ftp_ip}",
"-Dspring.data.mongodb.host=${mongo_ip}",
"/var/backend/license-system-0.0.1-SNAPSHOT.jar"
]
Am I missing something? Or am I doing something wrong?
If you want to use environmnet varibles in your entrypoint, you should use the "shell form" instead of the "exec form".
ENTRYPOINT java -jar -Dspring.quorum.host=${quorum_ip} -Dspring.ftp.server=${ftp_ip} -Dspring.data.mongodb.host=${mongo_ip} /var/backend/license-system-0.0.1-SNAPSHOT.jar
You could probably make it work with the "exec form" but it only complicates the syntax.
You have to use build args instead of envs to build an image from Dockerfile
Dockerfile
FROM alpine:latest
ARG ftp_ip
ARG mongo_ip
ARG quorum_ip
RUN apk add --update openjdk8 && mkdir /var/backend/
RUN apk update
COPY license-system-0.0.1-SNAPSHOT.jar /var/backend/
EXPOSE 8080
ENTRYPOINT [ "java", "-jar", "-Dspring.quorum.host="${quorum_ip}, "-Dspring.ftp.server="${ftp_ip}, "-Dspring.data.mongodb.host="${mongo_ip},"/var/backend/license-system-0.0.1-SNAPSHOT.jar" ]
docker-compose
version: "3"
services:
backend:
network_mode: host
build:
context: .
dockerfile: ./path/to/backend/Dockerfile
args:
- mongo_ip=${mongo_ip}
- ftp_ip=${ftp_ip}
- quorum_ip=${quorum_ip}
ports:
- "8080:8080"
.env (To pass envs for use in docker-compose. docker-compose automatically fetches envs from .env file if it exists)
ftp_ip=127.0.0.1
mongo_ip=127.0.0.1
quorum_ip=http://localhost:22000
And then run docker-compose build to build image with correct envs

Resources