docker-compose: Not able to connect to memcached container - ruby

I am learning docker. i want to add caching functionality in my application and hence using memcached. below is my docker-compose.yml file
version: "3"
services:
app:
build: .
volumes:
- .:/project
command: 'rails s -b 0.0.0.0 -p 3000'
container_name: 'test_rails'
ports:
- 3000:3000
depends_on:
- database
links:
- memcached
database:
image: postgres:latest
volumes:
- ./data:/var/lib/postgresql/data
environment:
POSTGRES_USER: docker-user
POSTGRES_PASSWORD: docker-password
POSTGRES_DB: docker-db
memcached:
build:
context: .
dockerfile: Dockerfile.memcached
command: 'tail -f /dev/null'
when i am trying to connect to memcached server which is inside memcached container from app container using below code
require 'dalli'
options = { :namespace => "app_v1", :compress => true }
dc = Dalli::Client.new('localhost:11211', options)
Then i am getting below error
WARN -- : localhost:11211 failed (count: 0) Errno::EADDRNOTAVAIL: Cannot assign requested address - connect(2) for "localhost" port 11211
Dalli::RingError: No server available
from /usr/local/bundle/gems/dalli-2.7.10/lib/dalli/ring.rb:46:in `server_for_key'
from /usr/local/bundle/gems/dalli-2.7.10/lib/dalli/client.rb:367:in `perform'
from /usr/local/bundle/gems/dalli-2.7.10/lib/dalli/client.rb:130:in `set'
from (irb):4
from /usr/local/bin/irb:11:in `<main>'
can someone help me in understanding and resolving this issue.

You can not access one docker service from another service using localhost as each service has its own ip address and like small vm of its own. Use service name instead of localhost and docker will resolve it with ip addres of target service,
`dc = Dalli::Client.new('memcached:11211', options)`

Change :
dc = Dalli::Client.new('localhost:11211', options)
to :
dc = Dalli::Client.new('memcached:11211', options)
When you set up containers from compose they are all connected to the default network created by compose. memcached is in this case the DNS name of memcached container and will be resolved to container IP automatically.

Related

Can't connect to Docker sql for Windows by hostname

I have next docker compose file (part of it)
version: '3.7'
services:
# DB Server ==========================================================================================================
mssqlsimple:
image: microsoft/mssql-server-windows-developer:2017-latest
volumes:
- ".\\Prm.DbContext.Application\\FullInit:C:\\data"
container_name: pbpmssqlsimple
ports:
#- "1403:1433"
- target: 1433
published: 1403
protocol: tcp
mode: host
networks:
- backend
environment:
ACCEPT_EULA: "Y"
SA_PASSWORD: "SP_116b626d-ed7e-4f5d123#"
...
after command docker-compose up i have instance of sql server and can to connect to it by IP (172.21.69.132) or alias id (0338726df5ba) from docker config.
but i can't connect by host name mssqlsimple (or pbpmssqlsimple)
fragment config json
I tried to do it, but failed
disable windows firewall
connect with port mssqlsimple, 1403
used simple syntax for ports "1403:1433"
Tell me please how to solve my problem

Can't reach server inside docker container from host

I am hosting a mysql server and a go http server in docker. I am unable to hit the http server from my host machine. My host machine is a mac.
I have tried using localhost:8080 and ipofserver:8080. I get the ip from the docker inspect. I am able to connect to my mysql server from my host, but i can't hit the server from the host.
Here is my docker ps output.
0.0.0.0:8080->8080/tcp
0.0.0.0:3306->3306/tcp, 33060/tcp
Below are my details:
Docker Desktop version 2.0.0.3.
docker-compose
version: '3.1'
services:
mysql:
image: mysql:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: mydb
volumes:
- mysql:/var/lib/mysql
ports:
- "3306:3306"
networks:
- mynetwork
server:
image: server:latest
networks:
- mynetwork
ports:
- "8080:8080"
volumes:
mysql: ~
networks:
mynetwork:
driver: "bridge"
mysql dockerfile
FROM mysql:8.0.16
COPY ./scripts/mysql/dbgen-v1.sql /docker-entrypoint-initdb.d/
EXPOSE 3306
server dockerfile
FROM golang:1.12.5
WORKDIR a/go/path
COPY . .
ENV GOBIN=/usr/local/bin
RUN go get github.com/go-sql-driver/mysql
RUN go get github.com/iancoleman/strcase
RUN go get github.com/jmoiron/sqlx
RUN go get github.com/spf13/cobra
RUN go get github.com/gorilla/websocket
RUN go get github.com/spf13/viper
RUN go install -v cmd/project/main.go
EXPOSE 8080
CMD ["main"]
(This answer is based on the chat we had in the comments)
In order to expose the web server from inside the container to the host it needs to bind to 0.0.0.0 and not to 127.0.0.1. Using 0.0.0.0 ensures that the web server binds to the bridge interface that can be accessed from the host side.
Relevant Docker docs: https://docs.docker.com/v17.09/engine/userguide/networking/default_network/binding/

Docker use ip from host

I have the problem, that I want to create multiple docker container (with docker-compose) and call each container with the ip address.
On a Linux host it works but not in Windows as host.
Example:
container 1 (php) ip: 192.168.100.10
container 2 (mysql) ip: 192.168.100.11
container 3 (nginx) ip: 192.168.100.12
so I want to add a hosts item with the ip of the nginx to use a hostname like project.local for develop on browser.
Have anyone a idea what I must do on windows to realize this?
Each container use a internal IP for the base system that you using with your containers, for example if you are using Linux all container will have an internal IP that can be seen between container, but not for the principal host, if you want to connect to the containers you will need to use the ports for example for MySQL 3306, if the containers aren't seen between it you will need to create links or networks using a docker compose or the bash to set up this configuration, here I adjunct an example:
https://docs.docker.com/compose/networking/#specify-custom-networks
version: "3"
services:
proxy:
build: ./proxy
networks:
- frontend
app:
build: ./app
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
networks:
frontend:
# Use a custom driver
driver: custom-driver-1
backend:
# Use a custom driver which takes special options
driver: custom-driver-2
driver_opts:
foo: "1"
bar: "2"
https://docs.docker.com/compose/networking/#links
version: "3"
services:
web:
build: .
links:
- "db:database"
db:
image: postgres

Docker Compose + Spring Boot + Postgres connection

I have a Java Spring Boot app which works with a Postgres database. I want to use Docker for both of them. I initially put just the Postgres in Docker, and I had a docker-compose.yml file defined like this:
version: '2'
services:
db:
container_name: sample_db
image: postgres:9.5
volumes:
- sample_db:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=sample
- POSTGRES_USER=sample
- POSTGRES_DB=sample
- PGDATA=/var/lib/postgresql/data/pgdata
ports:
- 5432:5432
volumes:
sample_db: {}
Then, when I issued the commands sudo dockerd and sudo docker-compose -f docker-compose.yml up, it was starting the database. I could connect using pgAdmin for example, by using localhost as server and port 5432. Then, in my Spring Boot app, inside the application.properties file I defined the following properties.
spring.datasource.url=jdbc:postgresql://localhost:5432/sample
spring.datasource.username=sample
spring.datasource.password=sample
spring.jpa.generate-ddl=true
At this point I could run my Spring Boot app locally through Spring Suite, and it all was working fine. Then, I wanted to also add my Spring Boot app as Docker image. I first of all created a Dockerfile in my project directory, which looks like this:
FROM java:8
EXPOSE 8080
ADD /target/manager.jar manager.jar
ENTRYPOINT ["java","-jar","manager.jar"]
Then, I entered to the directory of the project issued mvn clean followed by mvn install. Next, issued docker build -f Dockerfile -t manager . followed by docker tag 9c6b1e3f1d5e myuser/manager:latest (the id is correct). Finally, I edited my existing docker-compose.yml file to look like this:
version: '2'
services:
web:
image: myuser/manager:latest
ports:
- 8080:8080
depends_on:
- db
db:
container_name: sample_db
image: postgres:9.5
volumes:
- sample_db:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=sample
- POSTGRES_USER=sample
- POSTGRES_DB=sample
- PGDATA=/var/lib/postgresql/data/pgdata
ports:
- 5432:5432
volumes:
sample_db: {}
But, now if I issue sudo docker-compose -f docker-compose.yml up command, the database again starts correctly, but I get errors and exit code 1 for the web app part. The problem is the connection string. I believe I have to change it to something else, but I don't know what it should be. I get the following error messages:
web_1 | 2017-06-27 22:11:54.418 ERROR 1 --- [ main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool.
web_1 |
web_1 | org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections
Any ideas?
Each container has its own network interface with its own localhost. So change how Java points to Postgres:
spring.datasource.url=jdbc:postgresql://localhost:5432/sample
To:
spring.datasource.url=jdbc:postgresql://db:5432/sample
db will resolve to the proper Postgres IP.
Bonus. With docker-compose you don't need to build your image by hand. So change:
web:
image: myuser/manager:latest
To:
web:
build: .
I had the same problem and I lost some time to understand and solve this problem:
org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
I show all the properties so that everyone understands.
application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL82Dialect
spring.jpa.hibernate.ddl-auto=update
docker-compose.yml:
version: "3"
services:
springapp:
build: .
container_name: springapp
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/testdb
ports:
- 8000:8080
restart: always
depends_on:
- db
db:
image: postgres
container_name: db
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=testdb
- PGDATA=/var/lib/postgresql/data/pgdata
ports:
- 5000:5432
volumes:
- pgdata:/var/lib/postgresql/data
restart: always
volumes:
pgdata:
For start spring application with local database we use url localhost.
For connect to container with database we need change 'localhost' on your database service, in my case 'localhost' to 'db'.
Solution: add SPRING_DATASOURCE_URL environment in docker-compose.yml wich rewrite spring.datasource.url value for connect:
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/testdb
I hope this helps someone save his time.
You can use this.
version: "2"
services:
sample_db-postgresql:
image: postgres:9.5
ports:
- 5432:5432
environment:
- POSTGRES_PASSWORD=sample
- POSTGRES_USER=sample
- POSTGRES_DB=sample
volumes:
- sample_db:/var/lib/postgresql/data
volumes:
sample_db:
You can use ENV variable to change the db address in your docker-compose.
Dockerfile:
FROM java:8
EXPOSE 8080
ENV POSTGRES localhost
ADD /target/manager.jar manager.jar
ENTRYPOINT exec java $JAVA_OPTS -jar manager.jar --spring.datasource.url=jdbc:postgresql://$POSTGRES:5432/sample
docker-compose:
`
container_name: springapp
environment:
- POSTGRES=db`

docker-compose: connection refused between containers, but service accessible from host

TL;DR: How do I have to change my below docker-compose.yml in order to allow one container to use a service of another over a custom (non-standard) port?
I have a pretty common setup: containers for a web app (Padrino [Ruby]), Postgres, Redis, and a queueing framework (Sidekiq). The web app comes with its custom Dockerfile, the remaining services come either from standard images (Postgres, Redis), or mount the data from the web app (Sidekiq). They are ties together via the following docker-compose.yml:
version: '2'
services:
web:
build: .
command: 'bundle exec puma -C config/puma.rb'
volumes:
- .:/myapp
ports:
- "9000:3000"
depends_on:
- postgres
- redis
sidekiq:
build: .
command: 'bundle exec sidekiq -C config/sidekiq.yml -r ./config/boot.rb'
volumes:
- .:/myapp
depends_on:
- postgres
- redis
postgres:
image: postgres:9.5
environment:
POSTGRES_USER: my-postgres-user
POSTGRES_PASSWORD: my-postgres-pass
ports:
- '9001:5432'
volumes:
- 'postgres:/var/lib/postgresql/data'
redis:
image: redis
ports:
- '9002:6379'
volumes:
- 'redis:/var/lib/redis/data'
volumes:
redis:
postgres:
One key point to notice here is that I am exposing the containers services on non-standard ports (9000-9002).
If I start the setup with docker-compose up, the Redis and Postgres containers come up fine, but the containers for the web app and Sidekiq fail since they can't connect to Redis at redis:9002. Remarkably enough, the same setup works if I use 6379 (the standard Redis port) instead of 9002.
docker ps also looks fine afaik:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9148566c2509 redis "docker-entrypoint.sh" Less than a second ago Up About a minute 0.0.0.0:9002->6379/tcp rubydockerpadrino_redis_1
e6d47321c939 postgres:9.5 "/docker-entrypoint.s" Less than a second ago Up About a minute 0.0.0.0:9001->5432/tcp rubydockerpadrino_postgres_1
What's even more confusing: I can access the Redis container from the host via redis-cli -h localhost -p 9002 -n 0, but the web app and Sidekiq containers fail to establish a connection.
I am using this docker version on MacOS:
Docker version 1.12.3, build 6b644ec, experimental
Any ideas what I am doing wrong? I'd appreciate any hint how to get my setup running.
When you bind ports like this '9002:6379' you're telling Docker to forward traffic from localhost:9002 -> redis:6379. That's why this works from your host machine:
redis-cli -h localhost -p 9002 -n 0
However, when containers talk to each other, they are all connected to the same network by default (the Docker bridge or docker0). By default, containers can communicate with each other freely on this network, without needing any ports opened. Within this network, your redis container is listening for traffic on it's usual port (6379), host isn't involved at all. That's why your container to container communication works on 6379.

Resources