Docker build says directory already exists but it is not - linux

In dockerfile I am creating directory /var/log/nginx since it didn't exist in the container even though nginx.conf is set to save logs in /var/log/nginx
However, the docker build failed saying the directory /var/log/nginx already exists. But it doesn't.
Docker build error:
root#jsd-user-management:~/flask# docker build -t flask_app .
Sending build context to Docker daemon 716.8kB
Step 1/6 : FROM tiangolo/uwsgi-nginx-flask:python3.5
---> dea8fea96656
Step 2/6 : RUN mkdir /var/log/nginx
---> Running in 9e9ff86747a7
mkdir: cannot create directory ‘/var/log/nginx’: File exists
The command '/bin/sh -c mkdir /var/log/nginx' returned a non-zero code: 1
Inside Docker container:
root#jsd-user-management:~/flask# docker exec -it flask_jsd-user-management_1 bash
root#c6d43f610a51:/app/app# ls /var/log
root#c6d43f610a51:/app/app#
Surprisingly enough, when I attempt to create the directory from inside the container, it works. However, no logs are populated inside it.

You can use -p flag.
-p, --parents
no error if existing, make parent directories as needed
RUN mkdir -p /var/log/nginx
RUN ls /var/log/
It might be case parent director missing.

Related

Docker run "error while creating mount source path '[...]': mkdir [...]: permission denied"

I'm trying to mount a directory in Docker run:
docker run --restart always -t -v /home/dir1/dir2/dir3:/dirX --name [...]
But I get the error:
error while creating mount source path '/home/dir1/dir2/dir3': mkdir /home/dir1/dir2/dir3: permission denied.
All the directories exist for sure, and the strange thing is when trying to mount dir2 and not dir3 it is working ok:
docker run --restart always -t -v /home/dir1/dir2/:/dirX --name [...] # THIS IS WORKING
All the directories ('dir2' and 'dir3') have the same permissions: drwxr-x---
Any suggestions on what might be the problem? why one is working and the other don't?
Thanks
Check the permission for the folder you're trying to mount docker with ls -la, you might need to modify the permissons with chmod.
If you don't want to modify permissions, just add sudoto the beggining of the command.
sudo docker run --restart always -t -v /home/dir1/dir2/dir3:/dirX --name [...]

Docker: mount image's original /docker-entrypoint.sh to a volume in read/write mode

I try to mount image's original /docker-entrypoint.sh to a volume in read/write mode, in order to be able to change it easily from outside (without entering the container) and then restart the container to observe the changes.
I do it (in ansible) like this:
/app/docker-entrypoint.sh:/docker-entrypoint.sh:rw
If /app/docker-entrypoint.sh doesn't exist on the host, a directory /app/docker-entrypoint.sh (not a file, as wish) is created, and I get following error:
Error starting container e40a90eef1525f554e6078e20b3ab5d1c4b27ad2a7d73aa3bf4f7c6aa337be4f: 400 Client Error: Bad Request (\"OCI runtime create failed: container_linux.go:348: starting container process caused \"process_linux.go:402: container init caused \\\"rootfs_linux.go:58: mounting \\\\\\\"/app/docker-entrypoint.sh\\\\\\\" to rootfs \\\\\\\"/var/lib/docker/devicemapper/mnt/4d3e4f4082ca621ab5f3a4ec3f810b967634b1703fd71ec00b4860c59494659a/rootfs\\\\\\\" at \\\\\\\"/var/lib/docker/devicemapper/mnt/4d3e4f4082ca621ab5f3a4ec3f810b967634b1703fd71ec00b4860c59494659a/rootfs/docker-entrypoint.sh\\\\\\\" caused \\\\\\\"not a directory\\\\\\\"\\\"\": unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
If I touch /app/docker-entrypoint.sh (and set proper permissions) before launching the container - the container fails to start up and keeps restarting (I assume because the /app/docker-entrypoint.sh and therefore internal /docker-entrypoint.sh are empty).
How can I mount the original content of container's /docker-entrypoint.sh to the outside?
If you want to override docker-entry point it should be executable or in other words you have to set chmod +x your_mount_entrypoint.sh in the host then you can mount otherwise it will through permission error. As entrypoint script should be executable.
Second thing, As mentioned in the comment you can mount the file better to keep the entrypoint script in directory like docker-entrypoint/entrypoint.sh.
or if you want to mount specific file then both name should be same otherwise entrypoint script will not be overridden.
docker run --name test -v $PWD/entrypoint.sh:/docker-entrypoint/entrypoint.sh --rm my_image
or
docker run --name test -v $PWD/entrypoint.sh:/docker-entrypoint/entrypoint.sh:rw --rm my_image
See this example, entrypoint generated inside dockerfile and you can overide this from any script but it should be executable and should be mount to docker-entrypoint.
Dockerfile
FROM alpine
RUN mkdir -p /docker-entrypoint
RUN echo -e $'#!/bin/sh \n\
echo "hello from docker generated entrypoint" >> /test.txt \n\
tail -f /test.txt ' >> /docker-entrypoint/entrypoint.sh
RUN chmod +x /docker-entrypoint/entrypoint.sh
ENTRYPOINT ["/docker-entrypoint/entrypoint.sh"]
if you build and run it you will
docker build -t my_image .
docker run -t --rm my_image
#output
hello from docker generated entrypoint
Now if you want to overide
Create and set permission
host_path/entrypoint/entrypoint.sh
for example entrypoint.sh
#!/bin/sh
echo "hello from entrypoint using mounted"
Now run
docker run --name test -v $PWD/:/docker-entrypoint/ --rm my_image
#output
hello from entrypoint using mounted
Update:
If you mount directory of the host it will hide the content of docker image.
The workaround
Mount some directory other then entrypoint name it backup
add instruction in entrypoint to copy entrypoint to that location at run time
So it will create new file on the host directory instead
FROM alpine
RUN mkdir -p /docker-entrypoint
RUN touch /docker-entrypoint/entrypoint.sh
RUN echo -e $'#!/bin/sh \n\
echo "hello from entrypoint" \n\
cp /docker-entrypoint/entrypoint.sh /for_hostsystem/ ' >> /docker-entrypoint/entrypoint.sh
RUN chmod +x /docker-entrypoint/entrypoint.sh
ENTRYPOINT ["/docker-entrypoint/entrypoint.sh"]
Now if you run you will have the docker entrypoint in the host, as opposit as you want
docker run --name test -v $PWD/:/for_hostsystem/ --rm my_image

Docker mounting volume. Permission denied

I have a problem with creating new files in mounted docker volume.
Firstly after installation docker i added my user to docker group.
sudo usermod -aG docker $USER
Created as my $USER folder:
mkdir -p /srv/redis
And starting container:
docker run -d -v /srv/redis:/data --name myredis redis
when i want to create file in /srv/redis as a user which created container I have a problem with access.
mkdir /srv/redis/redisTest
mkdir: cannot create directory ‘/srv/redis/redisTest’: Permission denied
I tried to search in other threads but i didn't find appropriate solution.
The question title does not reflect the real problem in my opinion.
mkdir /srv/redis/redisTest
mkdir: cannot create directory ‘/srv/redis/redisTest’: Permission denied
This problem occurs very likely because when you run:
docker run -d -v /srv/redis:/data --name myredis redis
the directory /srv/redis ownership changes to root. You can check that by
ls -lah /srv/redis
This is normal consequence of mounting external directory to docker. To regain access you have to run
sudo chown -R $USER /srv/redis
I think /srv/redis/redisTest directory is created by user inside redis container, so it belong to redis container user.
Have you already check using ls -l to see that /srv/redis/redisTest directory belong to $USER?
This could also be related (as I just found out) to having SELinux activated. This answer on the DevOps Stack Exchange worked for me:
The solution is to simply append a :z to the [docker] run volume argument so that this:
docker run -v /host/foobar:/src_dir /bin/bash
becomes this:
docker run -it -v /host/foobar:/src_dir:z /bin/bash

Dockerfile VOLUME not working while -v works

When I pass volume like -v /dir:/dir it works like it should
But when I use VOLUME in my dockerfile it gets mountend empty
My Dockerfile looks like this
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install nano
ENV Editor="/usr/bin/nano"
ARG UID=1000
RUN useradd -u "$UID" -G root writer
RUN mkdir -p "/home/writer" && chown -R "$UID":1000 "/home/writer"
RUN mkdir -p "/home/stepik"
RUN chown -R "$UID":1000 "/home/stepik"
VOLUME ["/home/stepik"]
USER writer
WORKDIR /home/stepik
ENTRYPOINT ["bash"]
Defining the volume on the Dockerfile only tells docker that the volume needs to exist inside the container, not where to get the volume from. It's the same as passing the option -v /dir instead of -v /dir:/dir. The result is an "anonymous" volume with a guid you can see in docker volume ls. You can't pass the option inside the Dockerfile to identify where to mount the volume from, images you pull from the docker hub can't mount an arbitrary directory from your host and send the contents of that directory to a black hat machine on the internet by design.
Note that I don't recommend defining volumes inside the Dockerfile. See my blog post on the topic for more details.

Why I can't touch file when the docker image has volume?

I have a mybase:latest image like this:
FROM ubuntu:latest
VOLUME /var
Then I encountered an error when docker run:
docker run -it mybase:latest mkdir -p /var/test && touch /var/test/test.txt
touch: cannot touch ‘/var/test/test.txt’: No such file or directory
I noticed this question: Building Dockerfile fails when touching a file after a mkdir
But it did not solve my problem as it said:
You can only create files there while the container is running
I think during Docker creating that container, mkdir -p /var/test && touch /var/test/test.txt is executed after all the volumes are ready, so it should work.
Where is worry about my thought?
Maybe the && part isn't in the same shell as the one created for the container. (But is actually the shell where you type the docker run command)
Try:
docker run -it mybase:latest sh -c 'mkdir -p /var/test && touch /var/test/test.txt'
That way at least, the && part applies to the shell of the mkdir command.

Resources