I know that Docker Compose (compose) is a tool that among other things makes setting up interconnectivity between containers much easier, but I am trying to practice doing that without compose to see what that process is like (and gain a deeper appreciation for compose in the long run).
Is the reason it is hard to run an app (in my case rails) + a sql server without compose because they are isolated units, so they don't know about each others file system and so don't know how to locate one another and that's why we use compose? Is there another reason?
How would you approach connecting the containers without using compose? If it's helpful I posted some metadata about the two containers below.
When run docker inspect on my postgres container I see an ENV and network config of:
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/postgresql/12/bin",
"PGDATA=/var/lib/postgresql/data"
]
"Networks": {
"bridge": {
"NetworkID": "e68fdafe2110067389853515b05b09cd0ce75c500190fae85abff82417794b7f",
"EndpointID": "0d5564c073286bf7c1d708d52146653cf75705f34c1e175963eba4c158424399",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"MacAddress": "02:42:ac:11:00:02",
}
}
And for the rails container:
"Env": [
"PATH=/usr/local/bundle/bin:/usr/local/bundle/gems/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
]
"Networks": {
"bridge": {
"NetworkID": "e68fdafe2110067389853515b05b09cd0ce75c500190fae85abff82417794b7f",
"EndpointID": "e76ad694f04b7ca07e388ab39ab81b00409500d4c175b5ce9f90a8c740da7246",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"MacAddress": "02:42:ac:11:00:03",
}
}
Docker compose is handy when you have bunch of containers and you want to start/stop whole environment by using single commands like docker-compose up or docker-compose down. And as you noted it also creates some common stuff to help containers talk to each other - like networks.
If you want to make it hard to yourself you can always not use compose and start your containers manually and connect them to a common network :
docker network create mynetwork
this will create a network named mynetwork with default bridge driver.
Next you will have to run your containers and connect them to this network :
docker container run --network mynetwork --name container1 image1
docker container run --network mynetwork --name container2 image2
and this is similiar to what compose is doing - you can access those containers over this network by DNS names - container1 and container2.
Related
Let's say you're on Windows and you want to mount a volume like so:
docker run --name nginx -v "C:\\my\\path:/usr/share/nginx/html" -p "8080:80" nginx
This works perfectly with Docker Desktop, which uses WSL2.
However, with a custom Docker in WSL2, you'll get:
docker: Error response from daemon: invalid mode: /usr/share/nginx/html.
There are some questions covering this topic:
Docker on Windows without Docker Desktop volume mounting
Docker Desktop for Windows, having trouble w/ -v bind mount
How do you create a bind mount in Docker when running with the WSL2 backend?
Their bottom line is: Use /mnt/c/.... But Docker Desktop doesn't need this. When you inspect a container created by Docker Desktop, you'll even see:
"Mounts": [
{
"Type": "bind",
"Source": "C:\\my\\path",
"Destination": "/usr/share/nginx/html",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
}
],
How is it possible that Docker Desktop's WLS2 Docker daemon can handle Windows paths?
i'm using docker desktop , I have runned prometheus as a container :
the commande docker inspect is showing that this container is running on the gateway 172.17.0.2 on port 9090 .
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "a112bcf4dbabbfdb5b3e14c9d286469a482557c78d42854a5ae3e754ca44fd5d",
"EndpointID": "0ecc79513b555daebb51947a6a6a73bb26f0974542a6f79d14013b8b1572a589",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
but when this address is not rechable in my browser .
could any one please help
That's correct: you can't access the docker inspect IP address on a Windows host. You also can't access it from a MacOS host, if your Docker is more explicitly inside a virtual machine (using Docker Toolbox or a tool like Minikube for your Docker environment), or if you're calling from a different host from the container. This IP address is almost never useful and you shouldn't need to look it up at all.
When you start a container, you have the option to publish ports from it. If Prometheus normally listens on port 9000, this could look like
docker run \
-d \ # in the background
--name prometheus \ # with a name so it's easier to manage
-p 9123:9000 \ # host port 9123 -> container port 9000
bitnami/prometheus
The second port number must exactly match what the image is expecting. The first port number can be anything that's not otherwise in use. The ports are frequently the same but don't have to be.
Once you have this docker run -p option, you can use the first port number to access the container; http://localhost:9123 if you're on the same host (and aren't using Docker Toolbox or a similar VM-based setup).
If you don't have this option, docker stop and docker rm the existing container and docker run a new one with the right settings. This is extremely routine, very similar to using Ctrl+C to stop a command-line process and then run it with different command-line arguments.
I'm testing to see if two containers (tomcat and busybox) in a same network 'myNetwork' are able to communicate with each other.
I followed the steps:
Create a network, 'myNetwork'
docker network create -d bridge myNetwork
Run a 'myTomcat' container in 'myNetwork'
docker run -it --name myTomcat --net=myNetwork tomcat
Run a 'busybox' container in the same network as 'myTomcat' network. i.e 'myNetwork'
docker run -it --net=container:myTomcat busybox
Test if tomcat container is accessible from busybox container using wget command
docker container exec -it {busybox_container_id}
/# wget localhost:8080
Here I I got an error wget: server returned error: HTTP/1.1 404
I wonder why I can't connect to tomcat container from busybox container even though I configured both containers in the same network.
So I inspected by doing:
docker network inspect myNetwork
[
{
"Name": "myNetwork",
...
"Containers": {
"43ba4d7ae27753f8085f5697cf6afc4eb872dbdbd2cf18138e3c6e3f90d54d15":{
"Name": "myTomcat",
"EndpointID":"03a98...",
...
"IPv4Address": "172.20.0.2/16",
"IPv6Address": ""
}
}
]
docker inspect {tomcat_container_id}
[
...
"Networks": {
"myNetwork": {
"NetworkID": "54bf...",
...
"Gateway": "172.20.0.1",
"IPAddress": "172.20.0.2"
...
}
...
]
docker inspect {busybox_container_id}
[
...
"NetworkSettings": {
"Bridge": "",
...
"Networks": {}
}
...
]
It seems tomcat is in 'myNetwork', but inspecting busybox container doesn't seem to show any network information. I'd appreciate for any help
Using localhost always point to the current machine. Using it in a Docker container targets the current container.
If you need your containers to communicate in a Docker network you can make use of the embedded DNS server by using container names as host names. As you named your Tomcat container myTomcat you should be able to do:
wget myTomcat:8080
For implementing integration tests for a project that I'm working on, there's a requirement to run integration tests by spinning up services as docker containers. So there are 2 services that stay in a fixed state through out the tests and those services are added into a docker-compose file. I am starting those services at the beginning of the tests. After that for a group of tests, I need to start another service using docker run command and add that service into the same network that is created when I start the previous 2 services as docker-compose. Is that possible ?
I tried the following steps to ensure that adding a docker container to a network created by docker-compose is possible or not.
Sample docker-compose file.
version: '3.7'
services:
backend_service_1:
image: solsson/http-echo
networks:
- envoymesh
environment:
- PORT=8000
networks:
envoymesh:
name: envoymesh
driver: bridge
Run another docker container and try to add to the same network.
docker run solsson/http-echo -e PORT=9000 --network=envoymesh --driver=bridge
Run docker network inspect envoymesh to see the containers in the network. But I'm seeing only the container from the docker-compose.
"Containers": {
"bd3c1b20be141cc66144f24a7e7adeaaa894e694004139f88f2b9563c729e8e1": {
"Name": "docker-network_backend_service_1_1",
"EndpointID": "d43f97ef5f0948ed2f6c7e4045164439ebf2596176868efcf6640927c1bc376e",
"MacAddress": "02:42:ac:1b:00:02",
"IPv4Address": "172.27.0.2/16",
"IPv6Address": ""
}
},
What am I doing wrong here ? Is it possible to achieve my requirement ?? Thanks in advance.
PS: docker network connect envoymesh [container id] works.
Solution
It was a issue with the way that I was using the docker run command. It should be used like follows with image name at the end.
docker run -e PORT=8000 --network envoymesh solsson/http-echo
I'm not sure why the docker run command doesn't work but have you tried this:
docker network connect envoymesh container-name
Command format:
docker network connect [OPTIONS] NETWORK CONTAINER
Description:
Connects a container to a network. You can connect a container by name or by ID. Once connected, the container can communicate with other containers in the same network.
Source: network connect
I've made the follow edit to /etc/docker/daemon.json
{
"ip" : "[ip address]"
}
To confirm, I inspect the network with docker network inspect [id]
"Options": {
"com.docker.network.bridge.host_binding_ipv4": "[ip address]",
"com.docker.network.bridge.name": "docker0",
},
Yet somehow all containers are still responding to other ips on the server, not just the given IP.
How can I restrict docker to a specific ip?
NOTE:
https://docs.docker.com/v17.09/engine/userguide/networking/default_network/binding/
Or if you always want Docker port forwards to bind to one specific IP address, you can edit your system-wide Docker server settings and add the option --ip=IP_ADDRESS. Remember to restart your Docker server after editing this setting.
The config file "/etc/docker/daemon.json" affects the docker daemon and not the container instances.
You have to configure your docker instance to bind just on the ip you want.
For example with a direct run :
docker run --rm -p 127.0.0.1:80:80 nginx
This will make the container bind the port 80 only on the ip 127.0.0.1