ansible_default_ipv4.address undefined in docker ubuntu - docker

I am trying to run a simple ansible operation which should update a line in /etc/hosts:
- hosts: localhost
become: true
vars:
master_host: "ansible-master"
tasks:
- hostname: name="{{master_host}}"
- name: Add master host to /etc/hosts
lineinfile: dest=/etc/hosts line="{{ ansible_default_ipv4.address}} {{master_host}}"
regexp=".*{{master_host}}\s*$"
When I run this in virtualbox with ubuntu 16, it works fine.
When I run it in my ubuntu 16 Docker container, I get:
fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field
'args' has an invalid value, which appears to include a variable that
is undefined. The error was: 'ansible_default_ipv4' is
undefined\n\nThe error appears to have been in
'/home/user/ansible/manage-ansible-master.yml': line 11, column 5, but
may\nbe elsewhere in the file depending on the exact syntax
problem.\n\nThe offending line appears to be:\n\n - hostname:
name=\"{{master_host}}\"\n - name: Add master host to /etc/hosts\n
^ here\n"}
Where is ansible trying to pull the local ip from and why can't it do so in docker?
BTW I have installed net-tools in my docker container and it has an eth0 ip.
On virtualbox and in docker I have a line in /etc/hosts
ansible-master 127.0.1.1
UPDATE:
I run
ansible all --connection=local -m setup | less
on virtualbox ubuntu and Docker ubuntu.
On Virtualbox I get a lot of network-related info that I don't get on Docker:
"ansible_facts": {
"ansible_all_ipv4_addresses": [
<ip>,
<another ip>
],
"ansible_all_ipv6_addresses": [
<ipv6>,
<another ipv6>
],
Also in virtualbox I get
"ansible_default_ipv4": {
"address": <value>,
"alias": <value>,
"broadcast": <value>,
"gateway": <value>,
"interface": <value>,
"macaddress": <value>,
"mtu": <value>,
"netmask": <value>,
"network": <value>,
"type": <value>
},
None of this appears in Docker.

I have had a similar problem with fedora; the solution was to install the package that provides the 'ip' command (which is used to generate the fact your looking for). in the case of fedora 'dnf install iproute'.

For Ubuntu, you have to install the iproute2 package in your pre_tasks. Don't forget to gather facts again in another task with - setup: afterwards.

Use hostname flag to put your local container hostname in /etc/hosts:
docker run --hostname=my_hostname

Related

Interact with podman docker via socket in Redhat 9

I'm trying to migrate one of my dev boxes over from centos 8 to RHEL9. I rely heavily on docker and noticed when I tried to run a docker command on the RHEL box it installed podman-docker. This seemed to go smoothly; I was able to pull an image, launch, build, commit a new version without problem using the docker commands I knew already.
The problem I have encountered though is I can't seem to interact with it via the docker socket (which seems to be a link to the podman one).
If I run the docker command:
[#rhel9 ~]$ docker images
Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/redhat/ubi9 dev_image de371523ca26 6 hours ago 805 MB
docker.io/redhat/ubi9 latest 9ad46cd10362 6 days ago 230 MB
it has my images listed as expected. I should be able to also run:
[#rhel9 ~]$ curl --unix-socket /var/run/docker.sock -H 'Content-Type: application/json' http://localhost/images/json | jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3 100 3 0 0 55 0 --:--:-- --:--:-- --:--:-- 55
[]
but as you can see, nothing is coming back. The socket is up and running as I can ping it without issue:
[#rhel9 ~]$ curl -H "Content-Type: application/json" --unix-socket /var/run/docker.sock http://localhost/_ping
OK
I also tried the curl commands using the podman socket directly but it had the same results. Is there something I am missing or a trick to getting it to work so that I can interact with docker/podman via the socket?
Podman isn't implemented using a client/server model like Docker. By default there is no socket, because there's no equivalent to the docker daemon. Podman does provide a compatibility interface that you can use by enabling the podman.socket unit:
$ systemctl enable --now podman.socket
This exposes a Unix socket at /run/podman/podman.sock that responds to Docker API commands. But!
The socket connects you to podman running as root, whereas you've been running podman as a non-root user: so you won't see the same list of images, containers, networks, etc.
Some random notes:
Podman by default runs "rootless": you can run it as an unprivileged user, and all of its storage, metadata, etc, is stored in your home directory.
You can also run Podman as root, in which case the behavior is more like Docker.
If you enable the podman socket, you can replace podman-docker with the actual Docker client (and use things like docker-compose), although I have run into occasional issues with this. Mostly I just use podman, and run docker engine in a VM). You will need to configure Docker to look at the podman socket in /run/podman/podman.sock.
I have podman.socket enabled on my system, so this works:
$ curl --unix-socket /run/podman/podman.sock -H 'content-type: application/json' http://localhost/_ping
OK
Or:
$ curl --unix-socket /run/podman/podman.sock -H 'content-type: application/json' -sf http://localhost/containers/json | jq
[
{
"Id": "f0d9a880c45bb5857b24f46bcb6eeeca162eb68d574c8ba16c4a03703c2d60f4",
"Names": [
"/sleeper"
],
"Image": "docker.io/library/alpine:latest",
"ImageID": "14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab",
"Command": "sleep inf",
"Created": 1655418914,
"Ports": [],
"Labels": {},
"State": "running",
"Status": "Up 3 days",
"NetworkSettings": {
"Networks": {
"podman": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "podman",
"EndpointID": "",
"Gateway": "10.88.0.1",
"IPAddress": "10.88.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "06:55:82:1b:1a:41",
"DriverOpts": null
}
}
},
"Mounts": null,
"Name": "",
"Config": null,
"NetworkingConfig": null,
"Platform": null,
"AdjustCPUShares": false
}
]
I managed to solve my problem although I'm not entirely sure how the scenario came about. I was looking through the output of docker info and podman info and noticed that they both had the remote socket set as:
remoteSocket:
exists: true
path: /run/user/1000/podman/podman.sock
rather than /run/podman/podman.sock which is where I thought it was (this socket does actually exist on my machine). Looking at the systemd file for podman.socket I can see that the socket was specified as %t/podman/podman.sock and checking the man page for podman-system-service it specified the rootless socket as unix://$XDG_RUNTIME_DIR/podman/podman.sock (where my $XDG_RUNTIME_DIR=/run/user/1000.
To get it all working with my software I just needed to make sure the DOCKER_HOST env variable was correctly set e.g. export DOCKER_HOST=unix:///run/user/1000/podman/podman.sock

How to run podman commands on host from within container

In case of docker, this can be achieved by mounting docker.sock inside container.
But since there is no daemon in podman. What's the replacement for docker.sock?
I want to typically check the podman images presents on host and start a new container.
I'm using Podman with --privileged=true and root.
There is a new API (status: experimental) that was announced in a blog post in January 2020.
[root#fedora31 ~]# podman --version
podman version 1.8.0
[root#fedora31 ~]# podman system service --timeout 500000 unix://root/foobar.sock
This function is EXPERIMENTAL.
As the API is still experimental this might change but right now you could make a query like this:
[root#fedora31 ~]# curl -s --unix-socket /root/foobar.sock http://d/v1.24/images/json | python3 -m json.tool
[
{
"Containers": 0,
"Created": 1572319417,
"Id": "f0858ad3febdf45bb2e5501cb459affffacef081f79eaa436085c3b6d9bd46ca",
"Labels": {
"maintainer": "Clement Verna <cverna#fedoraproject.org>"
},
"ParentId": "",
"RepoDigests": [
"sha256:8fa60b88e2a7eac8460b9c0104b877f1aa0cea7fbc03c701b7e545dacccfb433"
],
"RepoTags": [
"docker.io/library/fedora:latest"
],
"SharedSize": 0,
"Size": 201095865,
"VirtualSize": 201095865,
"CreatedTime": "0001-01-01T00:00:00Z"
},
null
]
[root#fedora31 ~]#
The command python3 -m json.tool was added to pretty-print the JSON output.
I think the UNIX socket can be accessed from inside a container by using the bind-mounting technique (that was mentioned in the question).
According to the man page, the command podman system service also accepts the flag --varlink.
Using Varlink instead of the new API might be a better solution right now as it is more mature but it will be deprecated in the future.

Rabbitmq connection refused from Docker container to local host

I have a docker container running a java process that I am trying to connect to rabbitmq running on my localhost.
Here are the steps I've done so far:
On my Local machine (macbook running Docker version 1.13.0-rc3, build 4d92237 with firewall turned off)
I've updated my rabbitmq_env.conf file to remove RABBITMQ_NODE_IP_ADDRESS so I am not tied to connect via localhost and i have an admin rabbitmq user. (not trying with guest user)
I tested this via telnet on my local machine and have no issues telnet <local-ip> 5672
Inside my docker container
able to ping local-ip and curl rabbitmq admin api
curl -i -u username:password http://local-ip:15672/api/vhosts returns sucessfully
[{"name":"/","tracing":false}]
When i try to telnet from inside the container I get
"Connection closed by foreign host"
looking at the rabbitmq.logs
=ERROR REPORT====
closing AMQP connection <0.30526.1> (local-ip:53349 -> local-ip:5672):
{handshake_timeout,handshake}
My java stacktrace incase helpful
Caused by: java.net.ConnectException: Connection refused (Connection >refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at >java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at >java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.>java:206)
at >java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at >com.rabbitmq.client.impl.FrameHandlerFactory.create(FrameHandlerFactory.ja>va:32)
at >com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory.newCon>nection(RecoveryAwareAMQConnectionFactory.java:35)
docker network inspect bridge
[
{
"Name": "bridge",
"Id": "716f935f19a107225650a95d06eb83d4c973b7943b1924815034d469164affe5",
"Created": "2016-12-11T15:34:41.950148125Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {
"9722a49c4e99ca5a7fabe56eb9e1c71b117a1e661e6c3e078d9fb54d7d276c6c": {
"Name": "testing",
"EndpointID": "eedf2822384a5ebc01e5a2066533f714b6045f661e24080a89d04574e654d841",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
What am I missing?
for me this works fine!
I have been installed the image docker pull rabbitmq:3-management
and run
docker run -d --hostname haroldjcastillo --name rabbit-server -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin2017 -p 5672:5672 -p 15672:15672 rabbitmq:3-management
the most important is to add the connection and management ports -p 5672:5672 -p 15672:15672
See you host in docker
docker-machine ip
return in my case:
192.168.99.100
Go to management http://192.168.99.100:15672
For Spring Boot you can configure this or works good for another connections
spring.rabbitmq.host=192.168.99.100
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin2017
spring.rabbitmq.port=5672
Best wishes
For anyone else searching for this error, I'm using spring boot and rabbitmq in docker container, starting them with docker compose. I kept getting org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused from the spring app.
The rabbitmq hostname was incorrect. To fix this, I'm using the container names in the spring app configuration. Either put spring.rabbitmq.host=my-rabbit in spring's application.properties (or yml file), or in docker-compose.yaml add environment: SPRING_RABBITMQ_HOST: my-rabbit to the spring service. Of course, "my-rabbit" is the rabbitmq container name described in the docker-compose.yaml
I am using docker with linux container with rabbitmq:3-management and have created a dotnet core based web api. While calling from We API action method I faced the same issue and changed the value to "host.docker.internal"
following scenario worked for me
"localhost" on IIS Express
"localhost" on Docker build from Visual Studio
"host.docker.internal" on Docker build from Visual Studio
"Messaging": {
"Hostname": "host.docker.internal",
"OrderQueue": "ProductQueue",
"UserName": "someuser",
"Password": "somepassword" },
But facing the same issue when, the container created via docker build command, but not when container created using Visual Studio F5 command.
Now find the solution there are two ways to do it:
by default all the containers get added into "bridge" network go through with these steps
Case1: If you have already containers (rabbitmq and api) in the docker
and running then first check their ip / hostname
docker network ls
docker network inspect bridge # from this step you'll get to know what containers are associated with this
find the rabbitmq container and internal IP, apply this container name or IP and then run your application it will work from Visual Studio and Docker build and run command
Case2: if you have no containers running then you may like to create
your network in docker then follow these steps:
docker network create givenetworknamehere
add your container while using "docker run" command or after
Step2.1: if using docker run command for your container then;
docker run --network givenetworknamehere -d -p yourport:80 --name givecontainername giveyourimagename
Step2.2 if adding newly created network after container creation then use below
command docker network connect givenetworknamehere givecontainername
with these step you bring your container in your newly created same network and they can communicate.
Note: by default "bridge" network type get created
After a restart, all was working. I don't think Rabbit was using respecting .config changes

Docker 1.10 access a container by its hostname from a host machine

I have the Docker version 1.10 with embedded DNS service.
I have created two service containers in my docker-compose file. They are reachable each other by hostname and by IP, but when I would like reach one of them from the host machine, it doesn't work, it works only with IP but not with hostname.
So, is it possible to access a docker container from the host machine by it's hostname in the Docker 1.10, please?
Update:
docker-compose.yml
version: '2'
services:
service_a:
image: nginx
container_name: docker_a
ports:
- 8080:80
service_b:
image: nginx
container_name: docker_b
ports:
- 8081:80
then I start it by command: docker-compose up --force-recreate
when I run:
docker exec -i -t docker_a ping -c4 docker_b - it works
docker exec -i -t docker_b ping -c4 docker_a - it works
ping 172.19.0.2 - it works (172.19.0.2 is docker_b's ip)
ping docker_a - fails
The result of the docker network inspect test_default is
[
{
"Name": "test_default",
"Id": "f6436ef4a2cd4c09ffdee82b0d0b47f96dd5aee3e1bde068376dd26f81e79712",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1/16"
}
]
},
"Containers": {
"a9f13f023761123115fcb2b454d3fd21666b8e1e0637f134026c44a7a84f1b0b": {
"Name": "docker_a",
"EndpointID": "a5c8e08feda96d0de8f7c6203f2707dd3f9f6c3a64666126055b16a3908fafed",
"MacAddress": "02:42:ac:13:00:03",
"IPv4Address": "172.19.0.3/16",
"IPv6Address": ""
},
"c6532af99f691659b452c1cbf1693731a75cdfab9ea50428d9c99dd09c3e9a40": {
"Name": "docker_b",
"EndpointID": "28a1877a0fdbaeb8d33a290e5a5768edc737d069d23ef9bbcc1d64cfe5fbe312",
"MacAddress": "02:42:ac:13:00:02",
"IPv4Address": "172.19.0.2/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
As answered here there is a software solution for this, copying the answer:
There is an open source application that solves this issue, it's called DNS Proxy Server
It's a DNS server that resolves container hostnames, and when it can't resolve a hostname then it can resolve it using public nameservers.
Start the DNS Server
$ docker run --hostname dns.mageddo --name dns-proxy-server -p 5380:5380 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc/resolv.conf:/etc/resolv.conf \
defreitas/dns-proxy-server
It will set as your default DNS automatically (and revert back to the original when it stops).
Start your container for the test
docker-compose up
docker-compose.yml
version: '2'
services:
redis:
container_name: redis
image: redis:2.8
hostname: redis.dev.intranet
network_mode: bridge # that way he can solve others containers names even inside, solve elasticsearch, for example
elasticsearch:
container_name: elasticsearch
image: elasticsearch:2.2
hostname: elasticsearch.dev.intranet
Now resolve your containers' hostnames
from host
$ nslookup redis.dev.intranet
Server: 172.17.0.2
Address: 172.17.0.2#53
Non-authoritative answer:
Name: redis.dev.intranet
Address: 172.21.0.3
from another container
$ docker exec -it redis ping elasticsearch.dev.intranet
PING elasticsearch.dev.intranet (172.21.0.2): 56 data bytes
As well it resolves Internet hostnames
$ nslookup google.com
Server: 172.17.0.2
Address: 172.17.0.2#53
Non-authoritative answer:
Name: google.com
Address: 216.58.202.78
Here's what I do.
I wrote a Python script called dnsthing, which listens to the Docker events API for containers starting or stopping. It maintains a hosts-style file with the names and addresses of containers. Containers are named <container_name>.<network>.docker, so for example if I run this:
docker run --rm --name mysql -e MYSQL_ROOT_PASSWORD=secret mysql
I get this:
172.17.0.2 mysql.bridge.docker
I then run a dnsmasq process pointing at this hosts file. Specifically, I run a dnsmasq instance using the following configuration:
listen-address=172.31.255.253
bind-interfaces
addn-hosts=/run/dnsmasq/docker.hosts
local=/docker/
no-hosts
no-resolv
And I run the dnsthing script like this:
dnsthing -c "systemctl restart dnsmasq_docker" \
-H /run/dnsmasq/docker.hosts --verbose
So:
dnsthing updates /run/dnsmasq/docker.hosts as containers
stop/start
After an update, dnsthing runs systemctl restart dnsmasq_docker
dnsmasq_docker runs dnsmasq using the above configuration, bound
to a local bridge interface with the address 172.31.255.253.
The "main" dnsmasq process on my system, maintained by
NetworkManager, uses this configuration from
/etc/NetworkManager/dnsmasq.d/dockerdns:
server=/docker/172.31.255.253
That tells dnsmasq to pass all requests for hosts in the .docker
domain to the docker_dnsmasq service.
This obviously requires a bit of setup to put everything together, but
after that it seems to Just Work:
$ ping -c1 mysql.bridge.docker
PING mysql.bridge.docker (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.087 ms
--- mysql.bridge.docker ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.087/0.087/0.087/0.000 ms
To specifically solve this problem I created a simple "etc/hosts" domain injection tool that resolves names of local Docker containers on the host. Just run:
docker run -d \
-v /var/run/docker.sock:/tmp/docker.sock \
-v /etc/hosts:/tmp/hosts \
--name docker-hoster \
dvdarias/docker-hoster
You will be able to access a container using the container name, hostname, container id and vía the network aliases they have declared for each network.
Containers are automatically registered when they start and removed when they are paused, dead or stopped.
The easiest way to do this is to add entries to your hosts file
for linux: add 127.0.0.1 docker_a docker_b to /etc/hosts file
for mac: similar to linux but use ip of virtual machine docker-machine ip default
Similar to #larsks, I wrote a Python script too but implemented it as service. Here it is: https://github.com/nicolai-budico/dockerhosts
It launches dnsmasq with parameter --hostsdir=/var/run/docker-hosts and updates file /var/run/docker-hosts/hosts each time a list of running containers was changed.
Once file /var/run/docker-hosts/hosts is changed, dnsmasq automatically updates its mapping and container become available by hostname in a second.
$ docker run -d --hostname=myapp.local.com --rm -it ubuntu:17.10
9af0b6a89feee747151007214b4e24b8ec7c9b2858badff6d584110bed45b740
$ nslookup myapp.local.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: myapp.local.com
Address: 172.17.0.2
There are install and uninstall scripts. Only you need is to allow your system to interact with this dnsmasq instance. I registered in in systemd-resolved:
$ cat /etc/systemd/resolved.conf
[Resolve]
DNS=127.0.0.54
#FallbackDNS=
#Domains=
#LLMNR=yes
#MulticastDNS=yes
#DNSSEC=no
#Cache=yes
#DNSStubListener=udp

docker installed with brew fails on /var/run/docker.sock

I installed docker on my Mac, using brew:
$ brew install docker
Running docker with no arguments works fine and shows a list of commands, but running a search fails like this:
$ docker search riak
FATA[0000] Get http:///var/run/docker.sock/v1.17/images/search?term=riak: dial unix /var/run/docker.sock: no such file or directory. Are you trying to connect to a TLS-enabled daemon without TLS?
docker images fails the same way. How can I get this running?
Edit:
I ran
$ brew install boot2docker
$ boot2docker init
That failed with
error in run: Failed to initialize machine "boot2docker-vm": exit status 1
Hopefully this sheds some light on the situation:
$ boot2docker -v info
Boot2Docker-cli version: v1.5.0
Git commit: ccd9032
2015/03/09 12:48:51 executing: VBoxManage showvminfo boot2docker-vm --machinereadable
{
"Name": "boot2docker-vm",
"UUID": "978c667c-9e7b-4026-823e-fa9ccde98a47",
"Iso": "",
"State": "running",
"CPUs": 1,
"Memory": 128,
"VRAM": 8,
"CfgFile": "/Users/issactrotts/VirtualBox VMs/boot2docker-vm/boot2docker-vm.vbox",
"BaseFolder": "/Users/issactrotts/VirtualBox VMs/boot2docker-vm",
"OSType": "",
"Flag": 0,
"BootOrder": null,
"DockerPort": 0,
"SSHPort": 0,
"SerialFile": ""
}
Most likely DockerPort and SSHPort should not be 0.
I'm assuming that brew installed boot2docker, as there does not appear to be any other supported, non-experimental way to run Docker on a Mac. Following the instructions from that page, you need to run boot2docker init; boot2docker start and then, in every shell session in which you want to use any Docker commands, you have to run $(boot2docker shellinit) (The $(...) is required in order to execute the output of shellinit).

Resources