Docker linking container - hyperlink

I read the Docker guide and I've a question about this page : https://docs.docker.com/userguide/dockerlinks/
Near the end, it's written :
In addition to the environment variables Docker adds a host entry for the linked parent to the /etc/hosts file. Let's look at this file on the web container now.
root#aed84ee21bde:/opt/webapp
cat /etc/hosts
172.17.0.7 aed84ee21bde
. . .
172.17.0.5 db
What's the command line I should execute to have a look in the web container?
Thanks in advance !

Just before, they did: docker run --rm --name web2 --link db:db training/webapp env. In order to have the shell prompt, simply run bash in interactive mode: docker run --rm -it --name web2 --link db:db training/webapp bash then you can cat /etc/hosts
Alternatively, you can directly do docker run --rm --name web2 --link db:db training/webapp cat /etc/hosts

In addition to #creack response on how to look at the hosts file using a shell from inside a container, you can also access the file from the host machine.
sudo cat `docker inspect --format '{{.HostsPath}}' web2`
The above one liner inspects the container named web2 and uses a template (specified with --format) to return the path to the hosts file that is given to the container. Then it just uses cat to display it (it also uses sudo, to get the right access level since docker assigns the file to root)
An interesting side effect of this is that you can update the hosts file of a container (if you get root access to the host).

Related

403 with nginx for file located in binded volume with docker

I am trying to use my nginx server on docker but I cannot use the files / folder if they belong to my volume. Problem, the goal of my test is to keep a volume between the file in my computer and the container.
I have searched during 3 days and tried a lot of solution but no effects...( useradd, chmod, chown, www_data, etc.....)
I don't understand how is it possible to use ngnix, a volume and docker?
The only solution actually for me is to copy the folder of my volume in another folder, and so I can chown the folder and use NGIX. There is no official solution on the web and I am surprised because for me using docker with a volume binded with his container would be the basic for a daily work.
If someone has managed to implement it, I would be very happy if you could share you code. I need to understand what I am missing.
FYI I am working with a VM.
Thanks !
I think you are not passing the right path in the volume option. There are a few ways to do it, you can pass the full path or you can use the $(pwd) if you are using a Linux machine. Let's say you are on /home/my-user/code/nginx/ and your HTML files are on html folder.
You can use:
$ docker run --name my-nginx -v /home/my-user/code/nginx/html/:/usr/share/nginx/html:ro -p 8080:80 -d nginx
or
$ docker run --name my-nginx -v ~/code/nginx/html/:/usr/share/nginx/html:ro -p 8080:80 -d nginx
or
$ docker run --name my-nginx -v $(pwd)/html/:/usr/share/nginx/html:ro -p 8080:80 -d nginx
I've created an index.html file inside the html folder, after the docker run, I was able to open it:
$ echo "hello world" >> html/index.html
$ docker run --name my-nginx -v $(pwd)/html/:/usr/share/nginx/html:ro -p 8080:80 -d nginx
$ curl localhost:8080
hello world
You can also create a Dockerfile, but you would need to use COPY command. I'll give a simple example that's working, but you should improve this by using a version and etc..
Dockerfile:
FROM nginx
COPY ./html /usr/share/nginx/html
...
$ docker build -t my-nginx:0.0.1 .
$ docker run -d -p 8080:80 my-nginx:0.0.1
$ curl localhost:8080
hello world
You can also use docker-compose. By the way, those examples are just to give you some idea of how it works.

Docker how to pass a relative path as an argument

I would like to run this command:
docker run docker-mup deploy --config .deploy/mup.js
where docker-mup is the name the image, and deploy, --config, .deploy/mup.js are arguments
My question: how to mount a volume such that .deploy/mup.js is understood as the relative path on the host from where the docker run command is run?
I tried different things with VOLUME but it seems that VOLUME does the contrary: it exposes a container directory to the host.
I can't use -v because this container will be used as a build step in a CI/CD pipeline and as I understand it, it is just run as is.
I can't use -v because this container will be used as a build step in a CI/CD pipeline and as I understand it, it is just run as is.
Using -v to expose your current directory is the only way to make that .deploy/mup.js file inside your container, unless you are baking it into the image itself using a COPY directive in your Dockerfile.
Using the -v option to map a host directory might look something like this:
docker run \
-v $PWD/.deploy:/data/.deploy \
-w /data \
docker-mup deploy --config .deploy/mup.js
This would map (using -v ...) the $PWD/.deploy directory onto /data/.deploy in your container, set the current working directory to /data (using -w ...), and then run deploy --config .deploy/mup.js.
Windows - Powershell
If you're inside the directory you want to bind mount, use ${pwd}:
docker run -it --rm -d -p 8080:80 --name web -v ${pwd}:/usr/share/nginx/html nginx
or $pwd/. (forward slash dot):
docker run -it --rm -d -p 8080:80 --name web -v $pwd/.:/usr/share/nginx/html nginx
Just $pwd will cause an error:
docker run -it --rm -d -p 8080:80 --name web -v $pwd:/usr/share/nginx/html nginx
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to
delimit the name
Mounting a subdirectory underneath your current location, e.g. "site-content", $pwd/ + subdir is fine:
docker run -it --rm -d -p 8080:80 --name web -v $pwd/site-content:/usr/share/nginx/html nginx
In my case there was no need for $pwd, and using the standard current folder notation . was enough. For reference, I used docker-compose.yml and ran docker-compose up.
Here is a relevant part of docker-compose.yml.
volumes:
- '.\logs\:/data'

Docker run syntax

Can anyone clarify the syntax in this command:
$ docker run -d -P --name web -v /src/webapp:/webapp training/webapp python app.py
I can see that:
Host directory: /src/webapp
Container: /webapp
but what is training/webapp? Is that the image? If so, why is there a /?
And is everything after that (i.e. python app.py) the command that you want to run in the container?
=====
And to clarify with this command:
$ docker run -d -P --name web -v /webapp training/webapp python app.py
How does it work if you ONLY specify -v /webapp - is that equivalent to /webapp:/webapp?
You can find the documentation for docker run here
The basic structure looks like this:
$ docker run [OPTIONS] IMAGE[:TAG|#DIGEST] [COMMAND] [ARG...]
-d let's you run your docker container in detached mode, so you won't see the console output
-P publish all exposed ports to the host interfaces
--name the name of your container
-v the volume you mount host/path:container/path, where in your case /src/webapp is on your local machine and /webapp is inside your container
training/webapp is the username and image name for the docker image. I have linked the image's location on DockerHub for you
python app.pyare the command (python) and the argument run when the container starts (app.py)
Yes, training/webapp is image name. Dockerhub accept name this way only.
training is username and webapp is image name.
if you don't use dockerhub(this is image repository from docker pull image by default) and build image locally then you can give any name.
python app.py : command that will execute when docker up
--name web : this will be name of container
-v /src/webapp:/webapp : this will create volume webapp and mount on /src/webapp
--publish-all, -P : Publish all exposed ports to random ports
For more help see docker run Documentation.

How to re-mount a docker volume without overriding existing files?

When running Docker, you can mount files and directories using the --volume option. E.g.:
docker run --volume /remote ./local myimage
I'm running a docker image that defines VOLUMESs in the Dockerfile. I need to access a config file that happens to be inside one of the defined volumes. I'd like to have that file "synced" on the host so that I can edit it. I know I could run docker exec ..., but I hope to circumvent that overhead for only editing one file. I found out that the volumes created by the VOLUMES line are stored in /var/lib/docker/volumes/<HASH>/_data.
Using docker inspect I was able to find the directory that is mounted:
docker inspect gitlab-runner | grep -B 1 '"Destination": "/etc/gitlab-runner"' | head -n 1 | cut -d '"' -f 4
Output:
/var/lib/docker/volumes/9c233c085c36380c6c33035222c16e5d061368c5060cc81dda2a9a713a2b2b3b/_data
So the question is:
Is there a way to re-mount volumes defined in an image? OR to somehow get the directory easier than my oneliner above?
EDIT after comments by zeppelin I've tried rebinding the volume with no success:
$ mkdir etc
$ docker run -d --name test1 gitlab/gitlab-runner
$ docker run -d --name test2 -v ~/etc:/etc/gitlab-runner gitlab/gitlab-runner
$ docker exec test1 ls /etc/gitlab-runner/
certs
config.toml
$ docker exec test2 ls /etc/gitlab-runner/
# empty. no files
$ ls etc
# also empty
docker inspect shows correctly that the volume is bound to ~/etc, but the files inside the container at /etc/gitlab-runner/ seem lost.
$ docker run -d --name test1 gitlab/gitlab-runner
$ docker run -d --name test2 -v ~/etc:/etc/gitlab-runner gitlab/gitlab-runner
You've got two different volume types there. One I call an anonymous volume (a very long uuid visible when you run docker volume ls). The second is a host volume or bind mount that maps a directory on the host directly into the container. So each container you spun up is looking at different places.
Anonymous volumes and named volumes (docker run -d -v mydata:/etc/gitlab-runner gitlab/gitlab-runner) get initialized to the contents of the image at that directory location. This initialization only happens when the volume is empty and is mounted into a new container. Host volumes, as you've seen, only get the contents of the host filesystem, even if it's empty at that location.
With that background, the short answer to your question is no, you cannot mount a file inside the container back out to your host. But you can copy the file out with several methods, assuming you don't overlay the source of the file with a host volume mount. With a running container, there's the docker cp command. Personally, I like:
docker run --rm -v ~/etc:/target gitlab/gitlab-runner \
cp -av /etc/gitlab-runner/. /target/.
If you have a named volume with data you want to copy in or out, you can use any image with the tools you need to do the copy:
docker run --rm -v mydata:/source -v ~/etc:/target busybox \
cp -av /source/. /target/.
Try to avoid modifying data inside a container from the host directly, much nicer is when you wrap your task into another container that you then start with "--volumes-from" option when possible in your case.
Not sure I understood your problem, anyway, as for the documentation you mention,
The VOLUME instruction creates a mount point with the specified name
and marks it as holding externally mounted volumes from native host or
other containers. [...] The docker run command initializes the newly
created volume with any data that exists at the specified location
within the base image.
So, following the example Dockerfile , after having built the image
docker build -t mytest .
and having the container running
docker run -d -ti --name mytestcontainer mytest /bin/bash
you can access it from the container itself, e.g.
docker exec -ti mytestcontainer ls -l /myvol/greeting
docker exec -ti mytestcontainer cat /myvol/greeting
Hope it helps.

Understanding code executed after run command in Docker

I just saw the below script in the Docker doc's.
$ docker restart db
db
$ docker run -t -i --rm --link db:db training/webapp /bin/bash
root#aed84ee21bde:/opt/webapp# cat /etc/hosts
172.17.0.7 aed84ee21bde
. . .
172.17.0.9 db
What is happening after the run cammand is executed ? , the below part i mean:
root#aed84ee21bde:/opt/webapp# cat /etc/hosts
Can somebody explain this line by line, I fail to understand. Please this is really important to me.
docker run -t -i --rm --link db:db training/webapp /bin/bash
This line executes the command /bin/bash in a container created from the image training/webapp. /bin/bash is an interactive shell, and so executing it means that you're now in a shell inside the fake machine that is the Docker container. root#aed84ee21bde:/opt/webapp# is the shell's prompt, indicating that you are root on host aed84ee21bde with current directory /opt/webapp. cat /etc/hosts means the same thing here that it does outside the container, except that here it's referring to the /etc/hosts file inside the container, which is likely different from the one on your main system.

Resources