How to mount a single file in container in kubernetes/docker - docker

I have a single file which I want to mount in the container. The file is present in conf folder which also contains other file but the file I only want to mount is helper.conf. Doing this in docker:
docker run -it -v /path/to/dir/:/path/inside/container --name mycontainer dockerimage
Doing this throws below error:
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
To resolve this, I created another folder with name config inside conf and used below line:
docker run -it -v /path/to/dir/config:/path/inside/container --name mycontainer dockerimage
This works perfectly fine. Same is happening with kubernetes. Is it not possible to just mount a single file from a directory where other files are also present. Am I using wrong keywords for this.?
How can I resolve in Kubernetes?

The answer has been provided by #Ryan Dawson.
The best way to mount a single file in container (in Kubernetes) would be to use ConfigMap:
ConfigMaps allow you to decouple configuration artifacts from image
content to keep containerized applications portable.
ConfigMap can be used in this case to create a resource which will allow us to keep the configuration separate from the container image. As the configuration is a set of key-value pairs, it will allow to expose it as an environment variable that can be put inside the container or a volume. After creating ConfigMap, you will have to create a pod where you specify a ConfigMap it can consume to get necessary values.
In your situation, as Joel B and Tommy Nguyen specified in this Stack Overflow question :
You could use subPath like this to mount single file into existing directory.

Related

How to keep file from mounted volume and create new container with that file?

I have a docker container image that requires me to mount a volume containing a specific configuration file, in order for that container to properly start (this image is not one that I have control over, and is vendor supplied). If that volume is not mounted, the container will exit because the file is not found. So I need to put a configuration file in /host/folder/, and then:
docker run --name my_app -v /host/folder:/container/folder image_id
The application will then look in /container/folder/ for the file it needs to start.
I want to create/commit a new image with that file inside /container/folder/, but when that folder is mounted as volume from the host, docker cp will not help me do this, as far as I have tried. I think, as far as docker is concerned, the file copied there is no different than the files in the mounted volume, and will disappear when the container is stopped.
Part of the reason I want to do this, is because the file will not be changed, and should be there by default. The other reason is that I want to run this container in Kubernetes, and avoid using persistent volumes there to mount these directories. I have looked into using configmaps, but I'm not seeing how I can use those for this purpose.
If you can store the file into the ConfigMap you can mount the file to volume and use it inside the Kubernetes.
I am not sure with the type of file you have to use.
ConfigMap will inject this file into the volume of a POD so the application could access and use it.
In this case there will be no PVC required.
You can also follow this nice example showing how to mount the file into a volume inside a pod.
OR
Also, I am not sure about the docker image but if you can use that docker image you can add the file into the path, something like:
FROM <docker image>
ADD file ./container/folder/
In this case, you might have to check you can use the vendor docker image as a base and add the file into it.

How do I mount volumes on a docker container that is being created by another docker container?

I have a containerized REST API server using docker. I have mounted a folder on my host machine to this rest container using docker flag
--mount type=bind, source=<path/on/hostmachine>, target=<path/on/container>
This works perfectly and I can see real time mapping of files between my host and rest container. Now, my rest container generates a yaml file that contains the configuration for the new container that comes up and writes this configuration file to the shared volume mount.
I want to mount the same <path/on/hostmachine> that contains the configuration files generated by the rest container to the new container that comes up. The issue is, I do not bring the container up using the cli.
This is why I cannot use the --mount flag. I tried multiple ways to try doing it through the yaml file.
Blockquote
- Using absolute path as
volumes:
- <absolute/path/on/hostmachine>:<path/on/new/container>
did not work.
Blockquote
- Using volumes with type defined as
volumes:
- type: bind
source:<absolute/path/on/hostmachine>
target:<path/on/new/container>
did not work and gave volumes should be string error
How do I mount the same home directory to the new container that comes up on the rest container?
I figured out the issue in the first approach. I was using my path as "./Users/username/Desktop" instead of "/Users/username/Desktop" which was causing the path mismatch. I misunderstood the lack of errors. Rookie Mistake, Mea Culpa.

How to overwrite a file inside docker on Runtime

I want to overwrite a file that is inside a docker container with a file of same name on my host operating system.
Docker run -v does not overwrites this file as both file's name is same.
Any idea how I can achieve this?
I think you mean to keep the file synced between your host and your docker instance. You should use the docker run -v option as you wrote in the question but instead of giving the file name, you should use the folder name.
Further read on the topic: https://github.com/moby/moby/issues/15793
You can use docker cp to replace the file inside the Container with the one from the host. Thus you dont have to restart the container as e.g using volume mounts. Docker Cp Ref.

Docker file mount understanding

I'am using docker and I have a strange behaviour when I try to mount a container file on a host file.
docker run -v /var/tmp/foo.txt:/var/tmp/foo.txt myapp
The command above runs myapp container which creates a foo.txt file into the /var/tmp directory into the container. Because I need to keep this file on host after myapp dies, I create a mounting point.
My problem is that instead of creating foo.txt as a file on host, I end up with an empty directory named "foo.txt" (and nothing inside).
But, if I create an empty text file foo.txt on host and if I run myapp again, it works as expected.
So, my question is, Do I need to create the file on host before starting the container when I use file mount with docker?
I think I missed something. Thank you for your explanations.
In fact as you discovered, to mount a host file as a data volume the file must exists otherwise docker will create a directory and mount it.
From: https://docs.docker.com/engine/tutorials/dockervolumes/
Mount a host file as a data volume
The -v flag can also be used to mount a single file - instead of just directories - from the host machine.
$ docker run --rm -it -v ~/.bash_history:/root/.bash_history ubuntu /bin/bash
Note it never says that the file doesn't exists on host.
As suggested in the comment it is better to mount a directory if you want the container writes into it.
Regards

Creating a host directory as a data volume in Dockerfile

So when running the command for the container, I can create the host volume mount that I want with the command
docker run -d -P --name web -v /home/ec2-user:/home/ec2-user testing123
How can I turn that /src/webapp:/opt/webapp host directory into an argument inside of the Dockerfile? Can I use VOLUME to create this type of storage?
The reason I am asking is that when I tried to add it in with the arguments
VOLUME ["/home/ec2-user/:/home/ec2-user/" ]
It creates the directory inside of the container with no files except a :. How would I structure this argument to work with it?
You can't do what you want to do because host directory is dependent to your host and your Dockerfile hence your image must not be dependent to your host. Just 'expose' a volume and use docker run to map your host directory to that volume.
Note from Docker docs:
The host directory is, by its nature, host-dependent. For this reason,
you can’t mount a host directory from Dockerfile because built images
should be portable. A host directory wouldn’t be available on all
potential hosts.
Keep in mind that newer versions of Docker, won't create the directory in your host with -v /host/path:/container/path anymore. This was considered an anti-pattern and it was deprecated. You should manage your host file system with a different tool that gives you better guarantees.

Resources