I was trying to use variable substitution for a volume declaration. This led to the fallowing error:
ERROR: for php Cannot create container for service php: create .: volume name is too short, names should be at least two alphanumeric characters
Docker's Compose file:
services:
php:
image: php5-apache-composer
volumes:
- ${DIR}:/var/www/html
Is variable substitution supported for the volume declaration? I can use environment variables for any other declaration except this one.
You need to use .env file in folder where docker-compose.yaml is in order to declaring default environment variables for docker-compose.yaml file.
Just create .env file with the following content:
DIR=/var/www/html
Of course you can do that dinamically on each build like:
echo "DIR=/var/www/html" > .env && docker-compose up
I've run export DIR="/var/www/html" and sudo docker-compose run php -e DIR="/var/www/html"
The sudo creates a different environment for the command it's running, the DIR variable doesn't exist there. You can check that with a simple env command:
$ export USER_VAR=test
$ sudo env | grep USER_VAR
$
To get this to work, you'll need to either:
Create a .env and let docker-compose source the variable from that.
Run a shell with sudo -s and run both commands as root from there.
Run a shell as the sudo command, e.g.: sudo /bin/sh -c "DIR=/var/www/html docker-compose run php -e DIR=/var/www/html"
Related
We are trying some docker containers locally. For security purposes, user and password are used as env variables in the config file. The config file is copied as the volume in the docker-compose for one of the APIs. After docker-compose up, inside the container, we are still seeing the variable name and not the env variable value.
Config file inside the container copied as volume:
dbconfig:
dbuser: ${USER}
dbpass: ${PASSWORD}
dbname:
dbdrivername:
tablename
docker-compose.yaml:
services:
api:
image: ${API_IMAGE:api}:${VERSION:-latest}
ports:
- 8080:8080
environment:
- "USER=${USER}"
- "PASSWORD=${PASSWORD}"
volumes:
- ./conf/config.yaml:/etc/api.yaml
command: ["-config", "/etc/api.yaml"]
Config.yaml:
dbconfig:
dbuser: ${USER}
dbpass: ${PASSWORD}
dbname:
dbdrivername:
tablename
Please help us get rid of this error as we are newly adopting docker testing
Issue fixed with the solution mentioned here. How to run 2 different commands from docker-compose command:
We added the sed command in the entry point script which searches for the env variable inside the config and replaces it with the value. Env variables are passed from docker-compose for the service
sed \
-e "s/USER/${USER}/g" \
-e "s/PASSWORD/${PASSWORD}/g" \ -i /etc/api.yaml
I have seen the following links to execute multiple commands in docker-compose file:
Docker-Compose + Command
Using Docker-Compose, how to execute multiple commands
docker-compose run multiple commands for a service
which tell us how to execute multiple commands in docker-compose file (also in the docker container).
In order to run sburn/apache-atlas image properly, I have to set some environment variables which exists in /opt/apache-atlas-2.1.0/conf/atlas-env.sh directory.
I have tried the following docker-compose.yml file:
version: "3.3"
services:
atlas:
image: sburn/apache-atlas
container_name: atlas
ports:
- "21000:21000"
volumes:
- "./bash_script:/app"
command: bash -c "
source ./opt/apache-atlas-2.1.0/conf/atlas-env.sh
&& chmod 777 /app/import-hive.sh
&& /opt/apache-atlas-2.1.0/bin/atlas_start.py
"
Unfortunately, the first command (I mean source ./opt/apache-atlas-2.1.0/conf/atlas-env.sh) doesn't work. It doesn't have any error but the environment variables such as JAVA_HOME aren't set.
How are you checking that the variables are not set?
Run Docker exec -it atlas bash in the terminal.
Run set in the terminal. It shows all the environment variables.
Check whether the environment variables are set or not.
Your question involves a lot of stuff, if you can narrow it down people can help better. Here are my suggestions to debug it:
bash -exc "
echo home1=$JAVA_HOME
source ./opt/apache-atlas-2.1.0/conf/atlas-env.sh
echo home2=$JAVA_HOME
chmod 777 /app/import-hive.sh
echo home3=$JAVA_HOME
/opt/apache-atlas-2.1.0/bin/atlas_start.py
"
If JAVA_HOME is never set, there's something wrong with .sh file, either you fix that file or manually set it with
export JAVA_ENV=/aaa/bbb/ccc
Or defining it in your compose yaml file.
Also the way you're checking for env vars is wrong, running Docker exec -it atlas bash won't run in the same bash as bash -c "source ./opt/apache-a..."
to set enviroment variables you must set this:
environment:
- JAVA_HOME=/usr/bin/java
- OTHER_VARIABLE=example
Or you can set your variables on Dockerfile with:
ENV JAVA_HOME="Your variable"
ENV OTHER_VARIABLE="example"
If you want execute ./opt/apache-atlas-2.1.0/conf/atlas-env.sh script at the container start because this script have all environments that you need, you can include it on entrypoint or Dockerfile with CMD exec
Example:
FROM: source_image
RUN source ./opt/apache-atlas-2.1.0/conf/atlas-env.sh
ENTRYPOINT []
To execute commands from your docker-compose try this:
command: sh -c "source ./opt/apache-atlas-2.1.0/conf/atlas-env.sh"
Regards
Sources: docker-compose, run a script after container has started?
Given I have a dockerfile like:
ARG MAX_MEMORY_PER_NODE="10GB"
ENV P_MAX_MEMORY_PER_NODE="${MAX_MEMORY_PER_NODE}"
ENTRYPOINT ["/var/p/entrypoint.sh"]
And the entrypoint.sh does something like:
echo "Max memory ${P_MAX_MEMORY_PER_NODE}"
If I were to run the container using the defaults, I would expect
Max Memory 10GB
And that works, but if I run
docker run me/mycontainer:latest -e P_MAX_MEMORY_PER_NODE=1GB
The script still uses the default value (does not print 1GB instead). In fact if I ran:
docker run me/mycontainer:latest -e A_TEST=Hello
And the script had
echo "My test: ${A_TEST}"
It would output
My test:
What am I doing wrong here? What can't I override (or even set) the environment variables being used in the entrypoint script from docker run?
Set the environment variable before the image:
docker run -e "A_TEST=hello" alpine env
For docker-compose
Similar to the this answer: https://stackoverflow.com/a/48915478/11406645
when using docker-compose, and you are passing docker-compose.yaml file an environment variable, or overriding one in env_file; you should pass your environment variable like so: DEBUG=1 docker-compose up
Another problem I faced is that docker commands require sudo permissions:
If you are using sudo before the docker-compose command, add the environment variable after the sudo like so: sudo DEBUG=1 docker-compose up.
The wrong way:
DEBUG=1 sudo docker-compose up
The right way:
sudo DEBUG=1 docker-compose up
I have the following entryfile
FROM <image-of-nodejs>
COPY docker/node/entry.sh /var/entries/entry.sh
RUN apt-get update
RUN apt-get install ant -y
CMD ["/var/entries/entry.sh"]
the image is used by a docker-compose file:
version: "3.3"
services:
my_node:
build:
context: ./
dockerfile: docker/node/Dockerfile-build-dev
volumes:
- type: bind
source: ./
target: /var/proj
and the entry.sh file is the following:
#!/bin/bash
export QNAMAKER_SUB_KEY=b13615t
If I then start the image and I enter the docker, I won't find my env variable set:
docker-compose up --force-recreate -d
docker-compose run my_node bash
root#9c081bedde65:/# echo ${QNAMAKER_SUB_KEY}
<empty>
I would prefer to set my variables throug my script in place of the ENV Dockerfile command. What's wrong?
There are a couple of things going on here.
First, docker-compose run doesn't run a command inside the container you started with docker-compose up. It starts a new container to run a one-off command. You probably want docker-compose exec.
The reason you don't see the variable when using docker-compose run is that you are overriding your CMD by providing a new command (bash) on the docker-compose run command line.
You could consider:
Using ENV statements in your Dockerfile.
Using the environment key in your docker-compose.yml
The former will embed the information into your image, while the latter would mean that the variable would be unset if you didn't explicitly set it in your docker-compose.yaml file (or using -e on the docker run command line).
You may be able to accomplish your goal using an ENTRYPOINT script and setting the value there, but that won't impact the environment visible to you when using docker exec (or docker-compose exec).
I am confused, because it seems that an environment variable which is set in docker-compose.yml causes docker to rebuild my image on docker-compose up:
Dockerfile for apache_php_with_custom_docroot
FROM php:7.1.11-apache-jessie
# Set apache document root
ENV APACHE_DOCUMENT_ROOT /var/www/web
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
I'm building it with docker build -t apache_php_with_custom_docroot .
docker-compose.yml
version: "3"
services:
web:
image: apache_php_with_custom_docroot
environment:
- APACHE_DOCUMENT_ROOT=/var/www/anotherfolder
So, the strange thing to me is: It works to set the APACHE_DOCUMENT_ROOT. When I run docker-compose up -d apache uses the docroot /var/www/anotherfolder.
I was sure, when my image was build, then I can't change it in my docker-compose file. I read something about build parameters e.g. here: Docker-compose: Set a variable in env file and use it in Dockerfile
But I did not set build params. How does docker know, that he has to rebuild my image? Where can I read about the principles behind this?
define a entry point in your dockerfile like:
ENTRYPOINT bash $APACHE_DOCUMENT_ROOT/entrypoint.sh
And then in your entry point every time containers starts, you will be able to read mapped volume with a file and inject in your container or declare the environments or related startup task you will need
enviroment=$(cat /mapped_config/enviroment.env)
if grep -Fxq "$enviroment" /home/.bashrc
then
echo "Environment setted propertly"
else
echo "$enviroment" >> /home/.bashrc
echo "enviorment setted!"
fi
It's just an idea , and probably not the best way , is how i deal it in past.