I'm trying to access Redis server through the code and it's not connecting. But if i bash to the redis container i can access the redis-cli.
docker-compose.yml looks like this
version: '2'
services:
web:
build:
context: .
dockerfile: Dockerfile_nginx
ports:
- "9000:80"
environment:
- NGINX_SERVERNAME=xxx.dev *.xxx.dev
command: /bin/bash -c "envsubst '$$NGINX_SERVERNAME' < /var/www/site.template > /etc/nginx/conf.d/default.conf
&& dos2unix /var/www/provision/init_storage.sh && sh /var/www/provision/init_storage.sh
&& nginx -g 'daemon off;'"
volumes:
- .:/var/www
links:
- php
networks:
frontend
php:
build:
context: .
dockerfile: Dockerfile_php-fpm
command: /bin/bash -c "composer install
&& php-fpm"
volumes:
- .:/var/www
environment:
- APP_ENV=local
- APP_DEBUG=true
networks:
- frontend
- backend
links:
- redis
db:
build:
context: .
dockerfile: Dockerfile_mariadb
volumes:
- ./initdb:/docker-entrypoint-initdb.d
ports:
- "3309:3306"
environment:
MYSQL_ROOT_PASSWORD: xxxx
MYSQL_DATABASE: xxxx
networks:
- backend
redis:
build:
context: .
dockerfile: Dockerfile_redis
ports:
- "6379:6379"
networks:
frontend:
driver: bridge
backend:
driver: bridge
Dockerfile_redis
FROM redis:latest
When i try to connect to the redis server using this code
$redis = new \Redis();
try {
$redis->connect('127.0.0.1', 6379);
} catch (\Exception $e) {
var_dump($e->getMessage()) ;
die;
}
It gives this warning
Warning: Redis::connect(): connect() failed: Connection refused
Does anyone know how to connect Redis container to PHP container ?
Your Problem
Docker Compose creates separated docker container for different services. Each container are, logically speaking, like different separated computer servers that only connected with each other through docker network.
Consider each boxes in this diagram as an individual computer, then this is practically what you have:
+----------------------------------------------------------+
| your machine |
+----------------------------------------------------------+
|
+------ (virtual network by docker) -------+
| | |
+-----------------+ +-------------------+ +----------------+
| "php" container | | "redis" container | | "db" container |
+-----------------+ +-------------------+ +----------------+
Your PHP container doesn't see any redis in "localhost" because there is no redis in it. Just like it would't see any MySQL in "localhost". Your redis is running in the "redis" container. Your MySQL is running in your "db" container.
The things that confuses you is the port binding directives (i.e. ports
in this definition):
redis:
build:
context: .
dockerfile: Dockerfile_redis
ports:
- "6379:6379"
The port 6379
of the "redis" container is binded to your computer, but to your computer ONLY. Other container doesn't have the same access to the port bindings. So even your computer can connect it with '127.0.0.1:6379', the php
container cannot do the same.
Solution
As described in Networking in Docker Compose, each docker compose container can access other container by using the service name as hostname. For example, your programming running by service php
can access your MySQL service with the hostname db
.
So you should connect redis with its hostname redis
$redis = new \Redis();
try {
$redis->connect('redis', 6379);
} catch (\Exception $e) {
var_dump($e->getMessage()) ;
die;
}
just remove the redis port and change the redis hostname to redis
in your Laravel project .env file.
REDIS_HOST=redis
#REDIS_PORT=6379
If using a static-ip for your network use below instead of localhost
$redis->connect('<static-ip>', 6379);
Just write your container name into host in your .env
file. And run
artisan config:cache
docker-compose.yml Config
lnmp-redis:
image: yahuiwong/lnmp:redis3.2.9
hostname: lnmp-redis-v3
ports:
- "63789:63789"
Example
$redis = new \Redis();
var_dump($redis);
try {
$redis->connect('lnmp-redis-v3', 63789);
var_dump($redis->keys("*"));
} catch (\Exception $e) {
var_dump($e->getMessage()) ;
}