How to set uid and gid in Docker Compose? - bash

I can execute a docker run command as such ...
docker run --rm --user $(id -u):$(id -g) -e MYDATA=/some/path/to/data -e USER=$USER -p 8883-8887:8883-8887 ...
However, in Docker Compose, when I write out the following ...
version: '3.7'
services:
container_name: some-server
image: some:img
user: $(id -u):$(id -g)
...
... it does not work.
I understand I am asking docker-compose up to perform sub shell command substitution, and it cannot.
Is there any way to do this?

Try this
So, you need to put:
user: "${UID}:${GID}"
in your docker compose and provide UID and GID as docker-compose parameter
UID=${UID} GID=${GID} docker-compose up
(or define UID and GID as environment variables).

This can be done as well
In your docker-composer.yml
user: $DOCKER_USER
In the command line
echo 'export DOCKER_USER="$(id -u):$(id -g)"' >> ~/.bash_profile
source ~/.bash_profile
docker-compose up
Created a DOCKER_USER variable and added it in the bash_profile for persistency. The source will help the shell to recognize changes of .bash_profile on demand

add following command line arguments on docker build image:
docker build --build-arg UID="$(id -u)" --build-arg GID="$(id -g)" --build-arg UNAME="$(whoami)" . -t tagname -f docker.recipe
append following lines at the begin of the docker recipe:
FROM ubuntu:18.04 AS yoursystem
ARG UID
ARG GID
ARG UNAME
RUN groupadd -g ${GID} -o ${UNAME}
RUN useradd -m -u ${UID} -g ${GID} -o -s /bin/bash ${UNAME}

Related

Access argument from docker build inside script

So in dockerfile I am running entrypoint:
ARG WP_IMAGE=latest
FROM wordpress:$WP_IMAGE
ARG VERSION
RUN curl -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \
&& chmod +x /usr/local/bin/wp
RUN apt update && apt install -y vim
ADD ./bin/ /
RUN chmod +x /*.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["apache2-foreground"]
And I have this script entrypoint.sh:
#!/bin/bash
/usr/local/bin/docker-entrypoint.sh php-fpm || /configure.sh
exec "$#"
And there is configure.sh script and inside this script I want to access this argument from Dockerfile VERSION.
This is how I build my docker docker-compose build --build-arg WP_IMAGE=latest --build-arg VERSION=7.0 && docker-compose up -d.
You can use ENV keyword in Dockerfile like:
ARG VERSION
ENV VERSION=${VERSION}
Now the script running in the image can access VERSION from the environment.
The ENV instruction sets the environment variable to the value
. The environment variables set using ENV will persist when a
container is run from the resulting image.

How to bash into a docker container

trying to bash into container and do a for loop which simply performs a command (which works on a single file by the way). it even seems to echo the right command...what did I forget
Untitled
for pdf in *.pdf ;
do
docker run --rm -v "$(pwd):/home/docker" leofcardoso/pdf2pdfocr -g jpeg2000 -v -i '\'''$pdf''\''';
done
You can bash in a container with this commands:
To see the docker container id
docker container ls
To enter in bash inside a container.
docker exec -it CONTAINER_ID bash
First thing, you are not allocating tty in the docker run command and the docker container dies soon after converting files. Here is main process of container
#!/bin/bash
cd /home/docker
exec pdf2pdfocr.py "$#"
So, in this case, the life of this container is the life of exec pdf2pdfocr.py "$#" command.
As mentioned by #Fra, override the entrypoint and run the command manually.
docker run --rm -v "$(pwd):/home/docker" -it --entrypoint /bin/bash leofcardoso/pdf2pdfocr
but in the above run command, docker container will do not a thing and will just allocate the tty and the bash will open. So you can convert files inside your containers using docker exec and then run pdf2pdfocr.py -g jpeg2000 -v -i mypdf.pdf
So, if you want to run with override entry point then you can try.
docker run -it --rm --entrypoint /bin/bash -v "$(pwd):/home/docker" leofcardoso/pdf2pdfocr -c "pdf2pdfocr.py -g jpeg2000 -v -i mypdf.pdf"
or with the bash script
#!/bin/bash
for pdf in *.pdf ;
do
echo "converting $pdf"
docker run -it --rm --entrypoint /bin/bash -v "$(pwd):/home/docker" leofcardoso/pdf2pdfocr -c "pdf2pdfocr.py -g jpeg2000 -v -i $pdf"
done
But the container will die after completing the conversion.

How does docker run interpret dynamically generated --env arguments

I am trying to provide a dynamically generated list of --env VAR1 --env VAR2 --env-file env.list environment variables to docker run.
Unfortunately it is not working.
for --env mapped variables, the variables are not visible in the container.
for --env-file provided file, docker complains that it cannot find the file: docker: open "env.list": no such file or directory.
Details
Running:
# env_params contains either --env or --env-file arguments
MY_VAR=123
env_params='--env "MY_VAR"'
echo ${env_params}
docker run -it --rm \
${env_params} \
my_docker_image env | grep MY_VAR
will not output anything. MY_VAR is not visible inside the container. But:
MY_VAR=123
docker run -it --rm \
--env "MY_VAR" \
my_docker_image env | grep MY_VAR
will work and 123 will be printed.
In a similar way --env-file will not work when provided through env_params but will work when provided directly to the docker run command.
What am I doing wrong?
There are two issues here.
First, When you run, in your shell:
MY_VAR=123
You have not set an environment variable. You have set a local shell variable. When you use --env MY_VAR, you are telling Docker that you want to make the environment variable MY_VAR available inside the container, and since it doesn't exist you get nothing:
$ MY_VAR=123
$ docker run -it --rm -e MYVAR alpine env | grep MY_VAR
<crickets>
If you first export that to the environment:
$ export MY_VAR=123
$ docker run -it --rm -e MYVAR alpine env | grep MY_VAR
MY_VAR=123
Then it will work as you expect. Alternately, you can use the VARNAME=VARVALUE form of the --env option:
docker run -e "MY_VAR=${MY_VAR}" ...
The second issue has to do with how shell variable interpolation works. If you have:
env_params='--env "MY_VAR"'
docker run -it --rm \
${env_params} \
alpine env
Then the resulting command line is:
docker run -it --rm --env '"MY_VAR"' alpine env
That is, the argument you're passing to docker run includes literal double quotes. You can fix that through the use of the eval statement (keeping in mind that you'll need to modify your script to export MY_VAR):
eval docker run -it --rm \
${env_params} \
alpine env | grep MY_VAR
Alternately (and I would argue preferably) you can use your env_params variable as an array, as long as you're using bash:
env_params=(--env MY_VAR)
env_params+=(--env SOME_OTHER_VAR)
docker run -it --rm \
"${env_params[#]}" \
alpine env | grep MY_VAR
Which would result in the correct command line:
docker run -it --rm --env MY_VAR --env SOME_OTHER_VAR alpine env
I guess the summary here is that your issues ultimately have nothing to do with "how docker run interprets dynamically generated arguments", but have everything to do with "how shell variables and interpolation work".

Dockerfile CMD not running at container start

So i've written a Dockerfile for a project, i've defined a CMD to run on starting the container to bootstrap the application.
The Dockerfile looks like
# create our mount folders and volumes
ENV MOUNTED_VOLUME_DIR=sites
RUN mkdir /$MOUNTED_VOLUME_DIR
ENV PATH=$MOUNTED_VOLUME_DIR/sbin:$MOUNTED_VOLUME_DIR/common/bin:$PATH
RUN chown -Rf www-data:www-data /$MOUNTED_VOLUME_DIR
# Mount folders
VOLUME ["/$MOUNTED_VOLUME_DIR/"]
# Expose Ports
EXPOSE 443
# add our environment variables to the server
ADD ./env /env
# Add entry point script
ADD ./start.sh /usr/bin/startContainer
RUN chmod 755 /usr/bin/startContainer
# define entrypoint command
CMD ["/bin/bash", "/usr/bin/startContainer"]
The start.sh script, does some git stuff like cloning the right repo, setting environment vars, as well as starting supervisor.
The start script begins with this
#!/bin/bash
now=$(date +"%T")
echo "Container Start Time : $now" >> /tmp/start.txt
/usr/bin/supervisord -n -c /etc/supervisord.conf
I start my new container like this
docker run -d -p expoPort:contPort -t -i -v /$MOUNTED_VOLUME_DIR/$PROJECT:/$MOUNTED_VOLUME_DIR $CONTAINER_ID /bin/bash
when i login to the container i see that supervisor hasn't been started, and neither has nginx or php5-fpm. the /tmp/start.txt file with a timestamp set from the startContainer script doesn't exist, showing its never ran the CMD in the Dockerfile.
Any hints on to get this fixed would be great
This:
docker run -d -p expoPort:contPort -t -i -v /$MOUNTED_VOLUME_DIR/$PROJECT:/$MOUNTED_VOLUME_DIR $CONTAINER_ID /bin/bash
Says 'run /bin/bash' after instantiating the container. E.g. skip CMD.
Try this:
docker run -d -p expoPort:contPort -t -i -v /$MOUNTED_VOLUME_DIR/$PROJECT:/$MOUNTED_VOLUME_DIR $CONTAINER_ID

docker run -i -t image /bin/bash - source files first

This works:
# echo 1 and exit:
$ docker run -i -t image /bin/bash -c "echo 1"
1
# exit
# echo 1 and return shell in docker container:
$ docker run -i -t image /bin/bash -c "echo 1; /bin/bash"
1
root#4c064f2554de:/#
Question: How could I source a file into the shell? (this does not work)
$ docker run -i -t image /bin/bash -c "source <(curl -Ls git.io/apeepg) && /bin/bash"
# content from http://git.io/apeepg is sourced and shell is returned
root#4c064f2554de:/#
In my case, I use RUN source command (which will run using /bin/bash) in a Dockerfile to install nvm for node.js
Here is an example.
FROM ubuntu:14.04
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
...
...
RUN source ~/.nvm/nvm.sh && nvm install 0.11.14
I wanted something similar, and expanding a bit on your idea, came up with the following:
docker run -ti --rm ubuntu \
bash -c 'exec /bin/bash --rcfile /dev/fd/1001 \
1002<&0 \
<<<$(echo PS1=it_worked: ) \
1001<&0 \
0<&1002'
--rcfile /dev/fd/1001 will use that file descriptor's contents instead of .bashrc
1002<&0 saves stdin
<<<$(echo PS1=it_worked: ) puts PS1=it_worked: on stdin
1001<&0 moves this stdin to fd 1001, which we use as rcfile
0<&1002 restores the stdin that we saved initially
You can use .bashrc in interactive containers:
RUN curl -O git.io/apeepg.sh && \
echo 'source apeepg.sh' >> ~/.bashrc
Then just run as usual with docker run -it --rm some/image bash.
Note that this will only work with interactive containers.
I don't think you can do this, at least not right now. What you could do is modify your image, and add the file you want to source, like so:
FROM image
ADD my-file /my-file
RUN ["source", "/my-file", "&&", "/bin/bash"]

Resources