Using args in docker-compose file - docker

I have the following in my docker-compose.yml file
geth-testnet:
build:
context: .
dockerfile: Dockerfile
args:
GETH_REPO: 'https://github.com/ethereum/go-ethereum'
GETH_VERSION: 'v1.8.12'
RPC_LISTEN_PORT: 8546
command: "--rpcport ${RPC_LISTEN_PORT}"
entrypoint:
- "geth"
tty: true
image: geth-node-testnet:v1.8.12
container_name: geth-node-testnet
ports:
- '8546:8546'
volumes:
- /root/.ethereum
When I run, docker-compose up --build, expect it to run the following command:
geth -rpcport 8546
However, I get the following error
flag needs an argument: -rpcport
So, the value for RPC_LISTEN_PORT is not correctly substituted.
I have ARG RPC_LISTEN_PORT in my dockerfile

Double checked your question, seems command: "--rpcport ${RPC_LISTEN_PORT}" cannot utilize the value you put in docker-compose.yml.
So afford two solutions:
export RPC_LISTEN_PORT=8546 in bash before you do compose command.
New a .env file in the same folder, put RPC_LISTEN_PORT=8546 to it.

Related

Pass argument to container on runtime AFTER entrypoint

I have a docker-compose.yaml looking like this:
version: '3.9'
services:
sqlcl:
container_name: container_sqlcl
image: sqlcl
volumes:
- ./TNSNAMES.ORA:/opt/oracle/network/admin/TNSNAMES.ORA
environment:
- TNS_ADMIN=/opt/oracle/network/admin
entrypoint: ["sql", "mycredentials"]
build:
context: .
dockerfile: Dockerfile
args:
GIT_TOKEN: my_git_token
tty: true
I would like to pass a command when running the container (I don't want to put a command in my yaml file because I want the script to be passed as an argument), like this:
docker exec 1872dfa12f47 #"path_to_my_file.sql"
However, this executes #"path_to_my_file.sql" before the entrypoint reaches the sqlcl console, where it is supposed to run.
With a docker image, I would do the below:
docker run sqlcl #"path_to_my_file.sql"
And it would overwrite the CMD, but with an already created container it does not seem to work like that.
It works if I do this:
docker exec 1872dfa12f47 sql mycredentials #"path_to_my_file.sql"
But I would like to keep my ENTRYPOINT in my yaml file.

BUSYBOX script is wrong

I need to start script in busybox container which will outuput the date and words the busybox is running
when I'm up my compose file i just see that:
busybox_1 | tail: invalid number 'sh ./5sec.sh'
This is my script:
while true; do
sleep 5
date
echo busybox is running
done
It's my Dockerfile:
FROM busybox:noauto
COPY /5sec.sh /5sec.sh
RUN chmod 777 5sec.sh
CMD ./5sec.sh
It's my compose file (just in case) :
version: '3'
services:
nginx:
image: "nginx:latest"
env_file: .env
ports:
- $HTTP_PORT:80
volumes:
- nginx-vol:/var/log/nginx
busybox:
image: "busybox:noauto"
volumes:
- nginx-vol:/var/log/nginx
volumes:
nginx-vol:
Help me please. How to start script automaticly. (Sorry for bad English)
I don't know what is this docker image busybox:noauto (probably your local image - build by you), and I guess this is reason of your problem. It's look like this image have some RUN command with tail or something like it.
I propose to use some standard busybox from dockerhub for your base image, for example busybox:1:
FROM busybox:1
COPY /5sec.sh /5sec.sh
RUN chmod 777 5sec.sh
CMD ./5sec.sh
Second question you should use build instead of image in you docker-compose.yaml if you want build image by yourself from your Dockerfile:
version: '3'
services:
nginx:
image: "nginx:latest"
env_file: .env
ports:
- $HTTP_PORT:80
volumes:
- ./nginx-vol:/var/log/nginx
busybox:
build: .
volumes:
- ./nginx-vol:/var/log/nginx
This should solve your problem.
Notes:
chmod 777 isn't a good practice
script should start with Shebang - #!/bin/sh in your case

Docker: Why does my project have a .env file?

I'm working on a group project involving Docker that has a .env file, which looks like this:
DATABASE_URL=xxx
DJANGO_SETTINGS_MODULE=xxx
SECRET_KEY=xxx
Couldn't this just be declared inside the Dockerfile? If so, what is the advantage of making a .env file?
Not sure if I'm going in the right direction with this, but this Docker Docs page says (emphasis my own):
Your configuration options can contain environment variables. Compose
uses the variable values from the shell environment in which
docker-compose is run. For example, suppose the shell contains
POSTGRES_VERSION=9.3 and you supply this configuration:
db:
`image: "postgres:${POSTGRES_VERSION}"`
When you run docker-compose up with this configuration, Compose looks for the POSTGRES_VERSION environment variable in the shell and substitutes its value in. For this example, Compose resolves the image to postgres:9.3 before running the configuration.
If an environment variable is not set, Compose substitutes with an empty string. In the example above, if POSTGRES_VERSION is not set, the value for the image option is postgres:.
You can set default values for environment variables using a .env file, which Compose automatically looks for. Values set in the shell environment override those set in the .env file.
If we're using a .env file, then wouldn't I see some ${...} syntax in our docker-compose.yml file? I don't see anything like that, though.
Here's our docker-compose.yml file:
version: '3'
services:
server:
build:
context: ./server
dockerfile: Dockerfile
env_file: .env.dev
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- ./server:/app
ports:
- "8500:8000"
depends_on:
- db
stdin_open: true
tty: true
db:
image: postgres
client:
build:
context: ./client
dockerfile: Dockerfile
command: bash -c "npm install; npm run start"
volumes:
- ./client:/app
- /app/node_modules
ports:
- "3000:3000"
depends_on:
- server
Idea there is probably to have a place to keep secrets separated from docker-compose.yml, which you then can keep in VCS and/or share.

Dockerfile pass environments on docker compose build

I have written a Dockerfile which uses two arguments:
FROM jessie
MAINTAINER Zeinab Abbasimazar
#Build Arguments
ARG REP_USER
ARG REP_PASS
# Build
RUN echo 'REP_USER:'$REP_USER', REP_PASS:'$REP_PASS
I wrote a docker-compose.yml for build:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
args:
REP_USER: $REP_USER
REP_PASS: $REP_PASS
I don't want to define these arguments directly in the compose file, so I tried to send them during docker compose build:
REP_USER=myusername REP_PASS=mypassword docker-compose build
Which didn't work. I changed my Dockerfile to use these arguments as environment variables; so I removed ARG lines:
FROM jessie
MAINTAINER Zeinab Abbasimazar
# Build
RUN echo 'REP_USER:'$REP_USER', REP_PASS:'$REP_PASS
And docker-compose.yml:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
And ran REP_USER=myusername REP_PASS=mypassword docker-compose build; still no result.
I also tried to save these information into an env file:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
env_file:
- myenv.env
But it seems env files doesn't affect at build time; they are just take part into run time.
EDIT 1:
Docker version is 1.12.6 which doesn't support passing arguments with --build-arg.
EDIT 2:
I tried using .env file as described here:
cat .env
REP_USER=myusername
REP_PASS=mypassword
I then called docker-compose config which returned:
networks: {}
services:
ui:
build:
args:
REP_PASS: mypassword
REP_USER: myusername
context: /home/zeinab/Workspace/ZiZi-Docker/Test/test-exec-1
dockerfile: Dockerfile
version: '2.0'
volumes: {}
Which means this resolved my issue.
EDIT 3:
I also tried third section of docker-compose arg documentation in my docker-compose.yml file:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
args:
- REP_USER
- REP_PASS
And executed:
export REP_USER=myusername;export REP_PASS=mypassword;sudo docker-compose build --no-cache
Still not getting what I wanted.
You can set build arguments with docker compose as described here:
docker-compose build [--build-arg key=val...]
docker-compose build --build-arg REP_USER=myusername --build-arg REP_PASS=mypassword
Btw, AFAIK build arguments are a compromise between usability and deterministic building. Docker aims to build in a deterministic fashion. That is, wherever you execute the build the produced image should be the same. Therefore, it appears logical that the client ignores the environment (variables) it is executed in.
The correct syntax for variable substitution in a docker-compose file is ${VARNAME}.
Try with this one:
version: "2"
services:
ui:
build:
context: .
dockerfile: Dockerfile
args:
REP_USER: ${REP_USER}
REP_PASS: ${REP_PASS}
I finally found the solution. I mentioned it in the question too. I first tried it with fail, then I found out that I had a typo naming .env file; it was .evn.
I tried using .env file as described here:
cat .env
REP_USER=myusername
REP_PASS=mypassword
I then called docker-compose config which returned:
networks: {}
services:
ui:
build:
args:
REP_PASS: mypassword
REP_USER: myusername
context: /home/zeinab/Workspace/ZiZi-Docker/Test/test-exec-1
dockerfile: Dockerfile
version: '2.0'
volumes: {}
Which means this resolved my issue. I should mention that this answer was really helpful.

docker-compose not setting environment variables

When I run docker-compose build && docker-compose up redis, with environment specified in docker-compose.yaml and RUN env in the Dockerfile, the environment variables I set don't get printed.
Why does this not work?
I'm using docker-compose version 1.4.2.
Here are the relevant files:
docker-compose.yaml with environment as a list of KEY=value pairs:
redis:
build: ../storage/redis
ports:
- "6379:6379"
environment:
- FOO='bar'
docker-compose.yaml with environment as a dictionary:
redis:
build: ../storage/redis
ports:
- "6379:6379"
environment:
- FOO: 'bar'
Dockerfile:
FROM redis:2.6
MAINTAINER me#email.com
RUN mkdir -p /var/redis && chown -R redis:redis /var/redis
RUN echo '-------------- env ---------------'
RUN env
COPY redis.conf /usr/local/etc/redis/redis.conf
EXPOSE 6379
ENTRYPOINT ["redis-server", "/usr/local/etc/redis/redis.conf"]
That's normal
docker-compose only sets the environment variables specified in the environment directive in the docker-compose.yaml file during the run phase of the container, and not during the build phase.
So if you do docker-compose run --entrypoint "/bin/bash" redis -c env you will be able to see your env variables.
If you want to set variables inside your Dockerfile (to be able to see them during the build phase) you can add inside your dockerfile before your RUN env:
ENV FOO bar
Well
I have tested and found following solutions for docker compose with env file or without env file. I will show you two different approach
Lets say you have following docker compose yml file
version: '3.8'
services:
db:
image: postgres:13
volumes:
- "./volumes/postgres:/var/lib/postgresql/data"
ports:
- "5432:5432"
env_file: docker.env
Now you need to setup the postgres variable in a file called docker.env. Remember you need to keep the docker_compose.yml file and docker.env file in same folder.
Next, In the docker.env file you need to have the database variable and value like this:
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=myapp_db
Now hit docker-compose up . It should work.
Lets say now you dont like to specify the env file name in the docker-compose.yml file. So you have to write docker-compose.yml file like this:
version: '3.8'
services:
db:
image: postgres:13
volumes:
- "./volumes/postgres:/var/lib/postgresql/data"
ports:
- "5432:5432"
environments:
- POSTGRES_USER=${PGU}
-POSTGRES_PASSWORD=${PGP}
-POSTGRES_DB=${PGD}
Now your docker.env file should look like this:
PGU=postgres
PGP=postgres
PGD=myapp_db
now hit docker-compose --env-file docker.env up
you are good to go.
This is because you were using environment when (I guess) you wanted to use args inside the build block:
redis:
build:
context: ../storage/redis
args:
- FOO: 'bar'
ports:
- "6379:6379"
Your Dockerfile would define FUN in the (image) environment:
FROM redis:2.6
RUN mkdir -p /var/redis && chown -R redis:redis /var/redis
# Read FUN from (build) arguments
# (may define a default: ARG FUN='wow')
ARG FUN
# Define env variable FUN with value from ARG
ENV FUN=$FUN
RUN echo '-------------- env ---------------'
RUN env
COPY redis.conf /usr/local/etc/redis/redis.conf
EXPOSE 6379
ENTRYPOINT ["redis-server", "/usr/local/etc/redis/redis.conf"]
The environment block is used to define variables for the running container (when docker-compose up, NOT when docker-compose build).

Resources