How to remove data from docker volume? - docker

I prepared Docker image containing libraries needed for building my other project. I want to have a directory /myLibs with libraries from different projects, e.g:
/myLibs:
projectA
projectB
projectC
Dockerfile:
FROM my-base:1.0
VOLUME /myLibs
COPY projectA/bin/*.so* /myLibs/projectA/bin/
CMD /bin/bash
Built:
docker build -t my-libs:1.0 .
Then I want to update libs in this image every time when I rebuild projectA. So I prepared Dockerfile:
FROM my-libs:1.0 # I changed parent image, because /myLibs/projectB and /myLibs/projectC should remain
VOLUME /myLibs
RUN ls -al /myLibs && rm -rf /myLibs/projectA && ls -al /myLibs
RUN ls -al /myLibs
COPY projectA/bin/*.so* /myLibs/projectA/bin/
CMD /bin/bash
As a result I have old projectA libs in my volume:
Step 4 : RUN ls -al /myLibs && rm -rf /myLibs/projectA && ls -al /myLibs
---> Running in 1e3e25084e69
total 12
drwxr-xr-x 3 root root 4096 Jul 16 13:52 .
drwxr-xr-x 75 root root 4096 Jul 16 13:52 ..
drwxr-xr-x 4 root root 4096 Jul 16 13:51 projectA
total 8
drwxr-xr-x 2 root root 4096 Jul 16 13:52 .
drwxr-xr-x 75 root root 4096 Jul 16 13:52 ..
---> d5973da5965c
Removing intermediate container 1e3e25084e69
Step 5 : RUN ls -al /myLibs
---> Running in 1d93575b50c2
total 12
drwxr-xr-x 3 root root 4096 Jul 16 13:52 .
drwxr-xr-x 75 root root 4096 Jul 16 13:52 ..
drwxr-xr-x 4 root root 4096 Jul 16 13:51 projectA
---> 6d2a48a5b67b
How can I remove files from volume?

If you want to change the files on rebuild, you probably don't want to do it in the volume. The volume is generally for data you want to persist. Remember the volume mounting will occur after the container builds, so what's probably happening is the volume with the old data is mounting over any changes you are making in the image (re)build.
What are you using /myLibs for? If they are read-only files you want to set up in the build, you might be better off not using a volume and make them part of the image. If you want to modify them, it's probably better to manage that after the build - there is no real reason to rebuild the image if you are just changing files in a networked volume.

Related

How can I use "docker run --user" but with root priviliges

I have a Docker image which contains an analysis pipeline. To run this pipeline, I need to provide input data and I want to keep the outputs. This pipeline must be able to be run by other users than myself, on their own laptops.
Briefly, my root (/) folder structure is as follows:
total 72
drwxr-xr-x 1 root root 4096 May 29 15:38 bin
drwxr-xr-x 2 root root 4096 Feb 1 17:09 boot
drwxr-xr-x 5 root root 360 Jun 1 15:31 dev
drwxr-xr-x 1 root root 4096 Jun 1 15:31 etc
drwxr-xr-x 2 root root 4096 Feb 1 17:09 home
drwxr-xr-x 1 root root 4096 May 29 15:49 lib
drwxr-xr-x 2 root root 4096 Feb 24 00:00 lib64
drwxr-xr-x 2 root root 4096 Feb 24 00:00 media
drwxr-xr-x 2 root root 4096 Feb 24 00:00 mnt
drwxr-xr-x 1 root root 4096 Mar 12 19:38 opt
drwxr-xr-x 1 root root 4096 Jun 1 15:24 pipeline
dr-xr-xr-x 615 root root 0 Jun 1 15:31 proc
drwx------ 1 root root 4096 Mar 12 19:38 root
drwxr-xr-x 3 root root 4096 Feb 24 00:00 run
drwxr-xr-x 1 root root 4096 May 29 15:38 sbin
drwxr-xr-x 2 root root 4096 Feb 24 00:00 srv
dr-xr-xr-x 13 root root 0 Apr 29 10:14 sys
drwxrwxrwt 1 root root 4096 Jun 1 15:25 tmp
drwxr-xr-x 1 root root 4096 Feb 24 00:00 usr
drwxr-xr-x 1 root root 4096 Feb 24 00:00 var
The pipeline scripts are in /pipeline and are packaged into the image with a "COPY. /pipeline" instruction in my Dockerfile.
For various reasons, this pipeline (which is a legacy pipeline) is set up so that the input data must be in a folder such /pipeline/project. To run my pipeline, I use:
docker run --rm --mount type=bind,source=$(pwd),target=/pipeline/project --user "$(id -u):$(id -g)" pipelineimage:v1
In other words, I mount a folder with the data to /pipeline/project. I found I needed to use the --user to insure the output files would have the correct permissions - i.e. I would have read/write/exec access on my host computer after the container exits.
The pipeline runs but I have one issue: one particular software used by the pipeline automatically tries to produce (and I can't change that) 1 folder in $HOME (so / - which I showed above) and 1 folder in my WORKDIR (which I have set up in my Dockerfile to be /pipeline). These attempts fails, and I'm guessing it's because I am not running the pipeline as root. But I need to use --user to make sure my outputs have the correct permissions - i.e. that I don't require sudo rights to read these outputs etc.
My question is: how am I meant to handle this? It seems that by using --user, I have the correct permissions set for the mounted folder (/pipeline/projects) where many output files are successfully made, no problems there. But how can I ensure the other 2 folders are correctly made outside of that mount?
I have tried the following but not success:
Doing "COPY -chown myhostuid:mygroupid" . pipeline/". This works but I have to hardcode my uid and gid so that won't work if another colleague tries to run the image.
Adding a new user with sudo rights and making it run the image: "RUN useradd -r newuser -g sudo" (I also tried using the "root" group but no success). This just gives me outputs which require sudo rights to read/write/exec. Which is not what I want.
Am I missing something? I don't understand why it's "easy" to handle permissions for a mounted folder but so much harder for the other folders in a container. Thanks.
If your software doesn't rely on relative paths (~/, ./), you can just set $HOME and WORKDIR to a directory that any user can write:
ENV HOME=/tmp
WORKDIR /tmp
If you can't do that, you can pass the uid/gid via the environment to an entrypoint script running as root, chown/chmod as necessary, then drop privileges to run the pipeline (runuser, su, sudo, setuidgid).
For example (untested):
entrypoint.sh
#!/bin/bash
[[ -v "RUN_UID" ]] || { echo "unset RUN_UID" >&2; exit 1; }
[[ -v "RUN_GID" ]] || { echo "unset RUN_GID" >&2; exit 1; }
# chown, chmod, set env, etc.
chown $RUN_UID:$RUN_GID "/path/that/requires/write/permissions"
export HOME=/tmp
# Run the pipeline as a non-root user.
sudo -E -u "#$RUN_UID" -g "#$RUN_GID" /path/to/pipeline
Dockerfile
...
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
Finally, pass the user and group IDs via the environment when running:
docker run --rm --mount type=bind,source=$(pwd),target=/pipeline/project -e RUN_UID=$(id -u) -e RUN_GID=$(id -g) pipelineimage:v1

Files inside a docker image disappear when mounting a volume

Inside of docker image has several files in /tmp directory.
Example
/tmp # ls -al
total 4684
drwxrwxrwt 1 root root 4096 May 19 07:09 .
drwxr-xr-x 1 root root 4096 May 19 08:13 ..
-rw-r--r-- 1 root root 156396 Apr 24 07:12 6359688847463040695.jpg
-rw-r--r-- 1 root root 150856 Apr 24 06:46 63596888545973599910.jpg
-rw-r--r-- 1 root root 142208 Apr 24 07:07 63596888658550828124.jpg
-rw-r--r-- 1 root root 168716 Apr 24 07:12 63596888674472576435.jpg
-rw-r--r-- 1 root root 182211 Apr 24 06:51 63596888734768961426.jpg
-rw-r--r-- 1 root root 322126 Apr 24 06:47 6359692693565384673.jpg
-rw-r--r-- 1 root root 4819 Apr 24 06:50 635974329998579791105.png
When I type the command to run this image -> container.
sudo docker run -v /home/media/simple_dir2:/tmp -d simple_backup
Expected behavior is if I run ls -al /home/media/simple_dir2
then the files show up.
But actual behavior is nothing exists in /home/media/simple_dir2.
On the other hand, if I run the same image without the volume option such as:
sudo docker run -d simple_backup
And enter that container using:
sudo docker exec -it <simple_backup container id> /bin/sh
ls -al /tmp
Then the files exist.
TL;DR
I want to mount a volume (directory) on the host, and have it filled with the files which are inside of the docker image.
My env
Ubuntu 18.04
Docker 19.03.6
From: https://docs.docker.com/storage/bind-mounts/
Mount into a non-empty directory on the container
If you bind-mount into a non-empty directory on the container, the directory’s existing contents are obscured by the bind mount. This can be beneficial, such as when you want to test a new version of your application without building a new image. However, it can also be surprising and this behavior differs from that of docker volumes.
"So, if host os's directory is empty, then container's directory will override is that right?"
Nope, it doesn't compare them for which one has files; it just overrides the folder on the container with the one on the host no matter what.

creation of a folder in a specific /home folder from a derived docker image doesn't work

In a Dockerfile, I have existing folders from my derived image /home and /root. I cannot create a folder in the /home directory:
RUN mkdir -p /home/TEST_3
No error messages are display but I can see that the folder was not created.
The same command is working fine in the /root directory
Bother folder seems to be similar in term of permission:
drwxr-xr-x 2 root root 4096 Apr 24 2018 home
drwx------ 1 root root 4096 Jun 20 08:38 root
The hard link count is different. The problematic folder /homehas more permission
Another strange thing is that I can create a folder in /home using:
WORKDIR /home/TEST_2
but then any file that I create in this folder doesn't seems to exist.
Here a small Dockerfile to recreate this issue/feature
# Specify the base image and tag
FROM gcr.io/deeplearning-platform-release/pytorch-cpu:m27
RUN ls -la
RUN ls -la /home/
RUN ls -la /root/
## creation ofthe folder is working and the folder exist (and I can create a file in the new folder)
RUN mkdir -p /root/TEST_1
RUN ls -la /root/TEST_1
RUN touch /root/TEST_1/new_file.txt
RUN ls -la /root/TEST_1
## creation of the folder is working and the folder exist but the file created doesn't exist
WORKDIR /home/TEST_2
WORKDIR /
RUN ls -la /home/TEST_2
RUN touch /home/TEST_2/new_file.txt
RUN ls -la /home/TEST_2
## creation of the folder succeed (no error messages), but the folder doesn't exist
RUN mkdir -p /home/TEST_3
RUN ls -la /home/TEST_3
RUN touch /home/TEST_3/new_file.txt
RUN ls -la /home/TEST_3
and here the output:
docker build -f Dockerfile_test .
Sending build context to Docker daemon 37.89kB
Step 1/17 : FROM gcr.io/deeplearning-platform-release/pytorch-cpu:m27
---> 7eb6565a8cc6
Step 2/17 : RUN ls -la
---> Running in 1ced0ed2bf49
total 80
drwxr-xr-x 1 root root 4096 Oct 26 12:52 .
drwxr-xr-x 1 root root 4096 Oct 26 12:52 ..
-rwxr-xr-x 1 root root 0 Oct 26 12:52 .dockerenv
drwxr-xr-x 1 root root 4096 Jun 20 08:20 bin
drwxr-xr-x 2 root root 4096 Apr 24 2018 boot
drwxr-xr-x 5 root root 340 Oct 26 12:52 dev
-rwxr-x--x 1 root root 94 Jun 19 21:51 entrypoint.sh
-rwxr-xr-x 1 root root 0 Jun 20 08:38 env.sh
drwxr-xr-x 1 root root 4096 Oct 26 12:52 etc
drwxr-xr-x 2 root root 4096 Apr 24 2018 home
drwxr-xr-x 1 root root 4096 Jun 20 08:22 lib
drwxr-xr-x 2 root root 4096 Jun 12 16:55 lib64
drwxr-xr-x 2 root root 4096 Jun 12 16:54 media
drwxr-xr-x 2 root root 4096 Jun 12 16:54 mnt
drwxr-xr-x 1 root root 4096 Jun 20 08:23 opt
dr-xr-xr-x 226 root root 0 Oct 26 12:52 proc
drwx------ 1 root root 4096 Jun 20 08:38 root
drwxr-xr-x 1 root root 4096 Jun 20 08:33 run
-rwxr-x--x 1 root root 109 Jun 19 21:51 run_jupyter.sh
drwxr-xr-x 1 root root 4096 Jun 20 08:20 sbin
drwxr-xr-x 2 root root 4096 Jun 12 16:54 srv
dr-xr-xr-x 13 root root 0 Oct 26 12:52 sys
drwxrwxrwt 1 root root 4096 Jun 20 10:09 tmp
drwxr-xr-x 1 root root 4096 Jun 20 08:33 usr
drwxr-xr-x 1 root root 4096 Jun 12 16:55 var
Removing intermediate container 1ced0ed2bf49
---> 87dbdffa7315
Step 3/17 : RUN ls -la /home/
---> Running in 756f013caf7f
total 8
drwxr-xr-x 2 root root 4096 Apr 24 2018 .
drwxr-xr-x 1 root root 4096 Oct 26 12:52 ..
Removing intermediate container 756f013caf7f
---> 24419a25ac99
Step 4/17 : RUN ls -la /root/
---> Running in bde249ae0452
total 52
drwx------ 1 root root 4096 Jun 20 08:38 .
drwxr-xr-x 1 root root 4096 Oct 26 12:52 ..
-rw-r--r-- 1 root root 3106 Apr 9 2018 .bashrc
drwxr-xr-x 3 root root 4096 Jun 20 08:31 .cache
drwxrwsr-x 1 root root 4096 Jun 20 08:26 .conda
drwx------ 4 root root 4096 Jun 20 08:33 .config
-rw-r--r-- 1 root root 401 Jun 20 08:33 .gitconfig
drwxr-xr-x 3 root root 4096 Jun 20 08:38 .ipython
drwxr-xr-x 1 root root 4096 Jun 20 10:10 .jupyter
drwxr-xr-x 3 root root 4096 Jun 20 08:31 .npm
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
-rw-r--r-- 1 root root 405 Jun 20 10:10 .wget-hsts
drwxrwxrwx 1 root root 4096 Jun 20 10:09 miniconda3
Removing intermediate container bde249ae0452
---> f6e6b3780145
Step 5/17 : RUN mkdir -p /root/TEST_1
---> Running in 95ffe0bc574f
Removing intermediate container 95ffe0bc574f
---> a87cac09ec17
Step 6/17 : RUN ls -la /root/TEST_1
---> Running in b8fd10afa3ee
total 8
drwxr-xr-x 2 root root 4096 Oct 26 12:52 .
drwx------ 1 root root 4096 Oct 26 12:52 ..
Removing intermediate container b8fd10afa3ee
---> 87b173385d4b
Step 7/17 : RUN touch /root/TEST_1/new_file.txt
---> Running in cbdd9ac79955
Removing intermediate container cbdd9ac79955
---> 0f57f2c15855
Step 8/17 : RUN ls -la /root/TEST_1
---> Running in 0a7d46a44e9e
total 8
drwxr-xr-x 1 root root 4096 Oct 26 12:53 .
drwx------ 1 root root 4096 Oct 26 12:52 ..
-rw-r--r-- 1 root root 0 Oct 26 12:53 new_file.txt
Removing intermediate container 0a7d46a44e9e
---> 5413892c3b96
Step 9/17 : WORKDIR /home/TEST_2
---> Running in d0322094ae3b
Removing intermediate container d0322094ae3b
---> 9815f6870830
Step 10/17 : WORKDIR /
---> Running in f84feebf3db9
Removing intermediate container f84feebf3db9
---> 5c85f2fadd04
Step 11/17 : RUN ls -la /home/TEST_2
---> Running in 4644cbcd5c3c
total 8
drwxr-xr-x 2 root root 4096 Oct 26 12:53 .
drwxr-xr-x 3 root root 4096 Oct 26 12:53 ..
Removing intermediate container 4644cbcd5c3c
---> c82625e638d9
Step 12/17 : RUN touch /home/TEST_2/new_file.txt
---> Running in ac89ce336a51
Removing intermediate container ac89ce336a51
---> d9569d5ca42d
Step 13/17 : RUN ls -la /home/TEST_2
---> Running in 999f75b4ece1
total 8
drwxr-xr-x 2 root root 4096 Oct 26 12:53 .
drwxr-xr-x 3 root root 4096 Oct 26 12:53 ..
Removing intermediate container 999f75b4ece1
---> 57062c0ccf0a
Step 14/17 : RUN mkdir -p /home/TEST_3
---> Running in f9788ac58dc7
Removing intermediate container f9788ac58dc7
---> e88a503ae524
Step 15/17 : RUN ls -la /home/TEST_3
---> Running in 16ea32c637c6
ls: cannot access '/home/TEST_3': No such file or directory
The command '/bin/sh -c ls -la /home/TEST_3' returned a non-zero code: 2
I am using Docker version 19.03.4, build 9013bf5 on MacOS 10.14.6
My questions are the following:
where is comming the difference (be able to create a folder in/root but not in /home
how to fix this issue to be able to create a folder in /home and
be able to create files as well in the new folder.
TL;DR
what is the difference between /home and /root
/home has a volume associated with it
how to get around the issue
create the file on entry-point (after the container is built), OR create the file inside the volume (I use the first option in my long answer)
Long answer:
Running a docker inspect containerId after building the Image & container show theirs a volumes assocated with the home directory:
"Source": "/var/lib/docker/volumes/1447dbc568742221a757a650427f38fb485e42fc7c6e959f33966922fe862d13/_data",
"Destination": "/home",
The volume is RW (read write), so you can write to the file once inside the container. (I tested using docker exec -it containerId /bin/sh then touch /home/TEST_2/new_file.txt)
Try using an Entrypoint script to create the folders/files.
Edit:
I wanted to see for myself, but ran into a couple hurdles. The parent container (gcr.io/deeplearning-platform-release/pytorch-cpu:m27) already has an entrypoint.sh file.
Also, adding a CMD or ENTRYPOINT command will override the parents entrypoint container (which you probably want).
Working Solution:
From the host, COPY the entrypoint.sh file (Assuming you want to modify it on your host). docker cp containerId:/entrypoint.sh .
Modify the entrypoint, adding your TOUCH commands:
#!/bin/bash
touch /home/TEST_2/new_file.txt # <-- I added this
. /env.sh
. /root/miniconda3/etc/profile.d/conda.sh
conda activate base
exec "$#"
Change your dockerfile to copy the new entrypoint.sh, which will replace the existing one:
COPY entrypoint.sh /entrypoint.sh
Your listing commands on startup will be the same, however if you go into the container you will see your file:
# ls home/TEST_2
new_file.txt
#

docker: understanding image layers after building an image and after starting a container

I have build a docker image using the Dockerfile:
--Dockerfile
FROM scratch
ADD archlinux.tar /
ENV LANG=en_US.UTF-8
CMD ["/usr/bin/bash"]
--building the docker image:
docker build -t archlinux/base .
then checking the images:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
archlinux/base latest 7f4e7832243a 43 minutes ago 399MB
then go into the overlay2 folder and check what happens
root#  cd var/lib/docker/overlay2 
# ls -al
0d5db16fa33657d952e4d7921d9239b5a17ef579e03ecdd5046b63fc47d15038
now i try to run:
$ docker run -it archlinux/base
Now check the /var/lib/overlay2 folder
# ls -al
total 24
drwx------ 6 root root 4096 Mar 3 15:58 .
drwx--x--x 15 simha users 4096 Mar 3 07:25 ..
drwx------ 3 root root 4096 Mar 3 16:01 0d5db16fa33657d952e4d7921d9239b5a17ef579e03ecdd5046b63fc47d15038
drwx------ 4 root root 4096 Mar 3 16:01 500ef7ee5672b73c778e2080dda0ad7a9101d6b65e5bdb0b52f4e5d2f22fa2b3
drwx------ 4 root root 4096 Mar 3 15:58 500ef7ee5672b73c778e2080dda0ad7a9101d6b65e5bdb0b52f4e5d2f22fa2b3-init
drwx------ 2 root root 4096 Mar 3 15:58 l
Now i see more folders.
Why there was only one folder before the run and later it shows many folders in the overlay2.
If the check the images using docker command it shows the same as previous:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
archlinux/base latest 7f4e7832243a 43 minutes ago 399MB
How to understand the image and their layers in overlay2
First note that the contents of the /var/lib/docker/ directory is for the internal soup of Docker and should not be messed with.
In that directory, the contents of the overlay2 directory is to store the docker layers that constitute your docker images and containers. What is important to remember is that overlay2 is a file system using union mounts. In short, it will merge two folders into one. So when using the filesystem you might see one folder, but under the hood there are more. This is how docker makes layers.

Edit apache configuration in docker

First time docker user here, I'm using this image: https://github.com/dgraziotin/osx-docker-lamp
I want to make the apache in that container to use a configuration file from the host system. How do I do that?
I know I can use nsenter, but I think my changes will get deleted when the container is turned off.
Thank you
The best solution is using VOLUME.
docker pull dgraziotin/lamp
You need to copy /etc/apache2/ from container to current directory in host computer. Then you can do this:
cd ~
mkdir conf
docker run -i -t --rm -v ~/conf:/tmp/conf dgraziotin/lamp:latest /bin/bash
On container do:
ls /tmp/conf
cd /etc/apache2/
tar -cf /tmp/conf/apache-conf.tar *
exit
On host computer:
cd conf
tar -xf apache-conf.tar
cd ..
# alter your configuration in this file and save
vi conf/apache2.conf
# run your container : daemon mode
docker run -d -p 9180:80 --name web-01 -v ~/conf:/etc/apache2 dgraziotin/lamp:latest
docker ps
To list conf content on Container use:
docker exec web-01 ls -lAt /etc/apache2/
total 72
-rw-r--r-- 1 root root 1779 Jul 17 20:24 envvars
drwxr-xr-x 2 root root 4096 Apr 10 11:46 mods-enabled
drwxr-xr-x 2 root root 4096 Apr 10 11:45 sites-available
-rw-r--r-- 1 root root 7136 Apr 10 11:45 apache2.conf
drwxr-xr-x 2 root root 4096 Apr 10 11:45 mods-available
drwxr-xr-x 2 root root 4096 Apr 10 11:44 conf-enabled
drwxr-xr-x 2 root root 4096 Apr 10 11:44 sites-enabled
drwxr-xr-x 2 root root 4096 Apr 10 11:44 conf-available
-rw-r--r-- 1 root root 320 Jan 7 2014 ports.conf
-rw-r--r-- 1 root root 31063 Jan 3 2014 magic
Use docker exec web-01 cat /etc/apache2/apache2.conf to list content inside Container.
One the WEB page to test your environment.
I hope this help you.
You should use a Dockerfile to generate a new image containing your desired configuration. For example:
FROM dgraziotin/lamp
COPY my-config-file /some/configuration/file
This assumes that there is a file my-config-file located in the same directory as the Dockerfile. Then run:
docker build -t myimage
And once the build completes you will have an image named myimage available locally.

Resources