add hosts redirection in docker - docker

I use gitlab in a Virtual machine . And I will use gitlab-ci (in the same VM), with docker .
For access to my gitlab, I use the domain git.local ( redirect to my VM on my computer, redirect to the 127.0.0.1 in my VM ).
And when I launch the tests, the test return :
fatal: unable to access 'http://gitlab-ci-token:xxxxxx#git.local/thib3113/ESCF.git/': Couldn't resolve host 'git.local'
So My question is: How add a redirection for git.local to the container IP ? I see the arg -h <host> for docker, but I don't know how to tell gitlab to use this argument. Or maybe a configuration for tell docker to use the container dns?
I see this: How do I get a Docker Gitlab CI runner to access Git on its parent host?
but same problem, I don't know how add argument :/ .

According to the GitLab CI Runner Advanced configuration, you can try to play with the extra_hosts param in your GitLab CI runner.
In /etc/gitlab-runner/config.toml :
[[runners]]
url = "http://localhost/ci"
token = "TOKEN"
name = "my_runner"
executor = "docker"
[runners.docker]
host = "tcp://<DOCKER_DAEMON_IP>:2375"
image = "..."
...
extra_hosts = ["localhost:192.168.0.39"]
With this example, when inside the container running the test git will try to clone from localhost, it will use the 192.168.0.39 as IP for this hostname.

if you want to use dns in docker use dns-gen follow these simple steps by this step you can assign host name to multi docker containers.
1. First know your docker IP by Publishing this command
/sbin/ifconfig docker0 | grep "inet" | head -n1 | awk '{ print $2}' | cut -d: -f2
now note the output ip and time to start dns-gen container(ps: don't forget to add docker ip you get by issuing above command before :53:53)
docker run --detach \
--name dns-gen \
--publish dockerip:53:53/udp \
--volume /var/run/docker.sock:/var/run/docker.sock \
jderusse/dns-gen
Last thing: Register you new DnsServer in you resolv.conf
echo "nameserver dockerip" | sudo tee --append /etc/resolvconf/resolv.conf.d/head
sudo resolvconf -u
Now you should be able to access your docker container in browser :- http://containername.docker
Hope it works.. Thanks..
Shubhankit

Related

Connecting to named server from a docker container

I am trying to access a named postgres server from inside a docker container. I can access the server via it's IP address, but not its name. I've tried --net=host and -p ServerName:5432:5432 options on the docker run command.
I will demonstrate the issue:
# on the host
$ ping ServerName
# This works
$ ping 10.1.1.25
# Works
# Then enter container with:
$ winpty docker exec -it containerName bash
$ ping 10.1.1.25
# Works
$ ping ServerName
# Does NOT work
I would guess that I need to give docker some kind of mapping from the hosts knowlegde of the network to the container. I presume that would be through the network functionality, but I can't find any instructions that I understand.
And before anyone suggests it, the postgres instance cannot be moved, including being moved into a docker container of it's own.
Output of docker ps is:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
15c7903f7ccd imageName "tail -f /dev/null" 47 minutes ago Up 47 minutes 0.0.0.0:5432->5432/tcp, 0.0.0.0:8000->8888/tcp containerName
Solved: I needed to use the --dns option in docker run command. Then, inside the container, I needed to use the fully qualified name i.e. serverName.companyName.com instead of just serverName.
Thanks to #Dupinder Singh for pointing me to some useful DNS articles (see comments on the question).

Using Weave Net Docker Swarm Adapter to allow services to communicate

I have a Docker Swarm cluster setup as follows:
Setup on node 1
docker swarm init --advertise-addr ${NODE_1_IP} --data-path-port=7789
Setup on node 2
docker swarm join --advertise-addr ${NODE_2_IP} --token XXX ${NODE_1_IP}:2377
I have then installed weave on both nodes as follows.
sudo curl -L git.io/weave -o /usr/local/bin/weave
sudo chmod a+x /usr/local/bin/weave
docker plugin install weaveworks/net-plugin:latest_release
docker plugin disable weaveworks/net-plugin:latest_release
docker plugin set weaveworks/net-plugin:latest_release WEAVE_PASSWORD=XXX
docker plugin enable weaveworks/net-plugin:latest_release
I wanted to set a password because I need the network to be encrypted.
I then set up a network and a service. The constraint makes the service consist of one container running on node 2.
docker network create --driver=weaveworks/net-plugin:latest_release --attachable testnet_weave_encrypted
docker service create --network=testnet_weave_encrypted --name web_encrypted --publish 80 --replicas=1 --constraint 'node.labels.datastore001 == true' nginx:latest
Finally I test it inside another container running on node 1:
docker run --rm --name alpine --net=testnet_weave_encrypted -ti alpine:latest sh
apk add --no-cache curl
curl web_encrypted
This fails with the message:
curl: (7) Failed to connect to web_encrypted port 80: Host is unreachable
I know that web_encrypted is not wrong because when I try a different value I get a different error.
After bashing my head against this wall for hours I have discovered that I can do the following on node 1:
curl web_encrypted.1.lsrdyz8n66jdotaqgdzk9u1uo
And it works!
But of course this is useless to me because the exact container name will change every time the service recreates it.
Is this a bug in the weave plugin or have I missed a step in setting this up?
If you specify endpoint_mode as DNSRR, you should be able to use the service name as well as any aliases you specify. The weavenet network in the snippet below was created using the Weave network plugin.
host#docker service create --network name=weavenet,alias=ngx --endpoint-mode=dnsrr --name nginx nginx
host#docker run -it -d --name alpine --network=weavenet alpine:curl
host#docker exec -it alpine sh
/ # curl nginx
<!DOCTYPE html>
<html>
....
/ # curl ngx
<!DOCTYPE html>
<html>

Running Shiny app using Docker on DigitalOcean

I try to run a Shiny app on a remote server (here DigitalOcean) using Docker.
First, I created a package for my app as a .tar.gz file. Then:
Create the following Dockerfile:
FROM thinkr/rfull
COPY myapp_*.tar.gz /myapp.tar.gz
RUN R -e "install.packages('myapp.tar.gz', repos = NULL, type = 'source')"
COPY Rprofile.site /usr/local/lib/R/etc
EXPOSE 3838
CMD ["R", "-e myapp::run()"]
Create the following Rprofile.site
local({
options(shiny.port = 3838, shiny.host = "0.0.0.0")
})
Then I build the image using
docker build -t myapp .
I push the image to DockerHub using
docker tag myapp myrepo/myapp:latest
docker push myrepo/myapp
I connect to my droplet on DigitalOcean
eval $(docker-machine env mydroplet)
I create a container from my image on Dockerhub
docker run -d -p 3838:3838 myrepo/myapp
So far it seems to work fine. No message error and I got expected messages when I run docker logs mycontainer
The problem is that I do not know how to actually access the running container. When I connect to the droplet IP, I got nothing (This site can’t be reached). If use
docker inspect --format '{{ .NetworkSettings.IPAddress }}' mycontainer
I got an IP, it seems to be a local one ('172.17.0.2').
When I run docker ps here is what I got
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d4195XXXX myrepo/myapp "R '-e myapp::ru…" 10 days ago Up 10 days 0.0.0.0:3838->3838/tcp, 8787/tcp determined_brown
So the question is: how can I run my dockerized shiny app on my droplet IP address?
Check if you have added the firewall rule to allow connections to 3838 port.
https://www.digitalocean.com/docs/networking/firewalls/resources/troubleshooting/
First, you need to publish the port, which is what you already do.
Second, you need to access the IP address of the host machine where there port is published.
The easiest way is probably to check the output of docker-machine env mydroplet and use this IP, together with your published port.

How can I find the docker name from a program running inside Docker

For logging purposes I want to know the name of the Docker instance that my program is running under.
For example if I start it as:
docker run -d --name my-docker-name some/image
how can i find the actual docker name (my-docker-name, in this example) from a program running in it?
TL;DR: --hostname option.
Issue
Container's program cannot access its container's name.
Solution a) -dirty and not easy-
https://stackoverflow.com/a/36068029/5321002
Solution b)
Add the option -h|--hostname="" matching the same name as the docker container name. Then you just need to query the hostname from the program and you're done.
edit
Solution c)
Provide, as you suggested, a env-variable with the name. The overall command would look like as follow:
$name="custom-uniq-name"
$docker run -h $name --name $name -e NAME=$name image-to-run
if you add
-v /var/run/docker.sock:/var/run/docker.sock
to your
docker run
command, you expose docker socket to the container, and you will be able to launch docker commands, such as
docker ps --filter
Keep in mind that this is potentially dangerous, now your container has a privileged access to the host.

How to get the hostname of the docker host from inside a docker container on that host without env vars

What are the ways get the docker host's hostname from inside a container running on that host besides using environment variables? I know I can pass the hostname as an environment variable to the container at container creation time. I'm wondering how I can look it up at run time.
foo.example.com (docker host)
bar (docker container)
Is there a way for container bar running in docker host foo.example.com to get "foo.example.com"?
Edit to add use case:
The container will create an SRV record for service discovery of the form
_service._proto.name. TTL class SRV priority weight port target.
-----------------------------------------------------------------
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo.example.com.
where 20003 is a dynamically allocated port on the docker host for a service listening on some fixed port in bar (docker handles the mapping from host port to container port).
My container will run a health check to make sure it has successfully created that SRV record as there will be many other bar containers on other docker hosts that also create their own SRV records.
_service._proto.name. TTL class SRV priority weight port target.
-----------------------------------------------------------------
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo.example.com. <--
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo2.example.com.
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo3.example.com.
The health check will loop through the SRV records looking for the first one above and thus needs to know its hostname.
aside
I'm using Helios and just found out it adds an env var for me from which I can get the hostname. But I was just curious in case I was using docker without Helios.
You can easily pass it as an environment variable
docker run .. -e HOST_HOSTNAME=`hostname` ..
using
-e HOST_HOSTNAME=`hostname`
will call the hostname and use it's return as an environment variable called HOST_HOSTNAME, of course you can customize the key as you like.
note that this works on bash shell, if you using a different shell you might need to see the alternative for "backtick", for example a fish shell alternative would be
docker run .. -e HOST_HOSTNAME=(hostname) ..
I'm adding this because it's not mentioned in any of the other answers. You can give a container a specific hostname at runtime with the -h directive.
docker run -h=my.docker.container.example.com ubuntu:latest
You can use backticks (or whatever equivalent your shell uses) to get the output of hosthame into the -h argument.
docker run -h=`hostname` ubuntu:latest
There is a caveat, the value of hostname will be taken from the host you run the command from, so if you want the hostname of a virtual machine that's running your docker container then using hostname as an argument may not be correct if you are using the host machine to execute docker commands on the virtual machine.
You can pass in the hostname as an environment variable. You could also mount /etc so you can cat /etc/hostname. But I agree with Vitaly, this isn't the intended use case for containers IMO.
Another option that worked for me was to bind the network namespace of the host to the docker.
By adding:
docker run --net host
You can pass it as an environment variable like this. Generally Node is the host that it is running in. The hostname is defaulted to the host name of the node when it is created.
docker service create -e 'FOO={{.Node.Hostname}}' nginx
Then you can do docker ps to get the process ID and look at the env
$ docker exec -it c81640b6d1f1 env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=c81640b6d1f1
TERM=xterm
FOO=docker-desktop
NGINX_VERSION=1.17.4
NJS_VERSION=0.3.5
PKG_RELEASE=1~buster
HOME=/root
An example of usage would be with metricbeats so you know which node is having system issues which I put in https://github.com/trajano/elk-swarm:
metricbeat:
image: docker.elastic.co/beats/metricbeat:7.4.0
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /sys/fs/cgroup:/hostfs/sys/fs/cgroup:ro
- /proc:/hostfs/proc:ro
- /:/hostfs:ro
user: root
hostname: "{{.Node.Hostname}}"
command:
- -E
- |
metricbeat.modules=[
{
module:docker,
hosts:[unix:///var/run/docker.sock],
period:10s,
enabled:true
}
]
- -E
- processors={1:{add_docker_metadata:{host:unix:///var/run/docker.sock}}}
- -E
- output.elasticsearch.enabled=false
- -E
- output.logstash.enabled=true
- -E
- output.logstash.hosts=["logstash:5044"]
deploy:
mode: global
I think the reason that I have the same issue is a bug in the latest Docker for Mac beta, but buried in the comments there I was able to find a solution that worked for me & my team. We're using this for local development, where we need our containerized services to talk to a monolith as we work to replace it. This is probably not a production-viable solution.
On the host machine, alias a known available IP address to the loopback interface:
$ sudo ifconfig lo0 alias 10.200.10.1/24
Then add that IP with a hostname to your docker config. In my case, I'm using docker-compose, so I added this to my docker-compose.yml:
extra_hosts:
# configure your host to alias 10.200.10.1 to the loopback interface:
# sudo ifconfig lo0 alias 10.200.10.1/24
- "relevant_hostname:10.200.10.1"
I then verified that the desired host service (a web server) was available from inside the container by attaching to a bash session, and using wget to request a page from the host's web server:
$ docker exec -it container_name /bin/bash
$ wget relevant_hostname/index.html
$ cat index.html
OK, this isn't the hostname (as OP was asking), but this will resolve to your docker host from inside your container for connectivity purposes.
host.docker.internal
I was redirected here when googling for this.
HOSTIP=`ip -4 addr show scope global dev eth0 | grep inet | awk '{print $2}' | cut -d / -f 1 | sed -n 1p`
docker run --add-host=myhost:${HOSTIP} --rm -it debian
Now you can access the host under the alias "myhost"
The first line won't run on cygwin, but you can figure out some other way to obtain the local IP address using ipconfig.
you can run:
docker run --network="host"
for sending the value of the machine host to the container.
I ran
docker info | grep Name: | xargs | cut -d' ' -f2
inside my container.
I know it's an old question, but I needed this solution too, and I acme with another solution.
I used an entrypoint.sh to execute the following line, and define a variable with the actual hostname for that instance:
HOST=`hostname --fqdn`
Then, I used it across my entrypoint script:
echo "Value: $HOST"
Hope this helps

Resources