I have a docker compose file which combines nginx and php like this:
nginx:
image: nginx
ports:
- "80:80"
- "2443:2443"
links:
- phpfpm
volumes:
- ./nginx/anonymous.conf:/etc/nginx/conf.d/anonymous.conf
- ./logs/nginx-error.log:/var/log/nginx/error.log
- ./logs/nginx-access.log:/var/log/nginx/access.log
- ./public:/usr/share/nginx/html
phpfpm:
image: php:fpm
expose:
- "2443"
volumes:
- ./public:/usr/share/nginx/html
I can see my website i.e index.php page on browser with the virtual host i have already made lets say anonymous.com
Now inside my phpfpm container i started a socket server based on Ratchet which is listening to port 2443
// bin/server.php
$webSocketServer = new WsServer(new Chat());
$server = IoServer::factory(
new HttpServer($webSocketServer), 2443);
$server->run();
This is how i run my server inside phpfpm container
php /usr/share/nginx/html/bin/server.php
My understanding is, since i have already exposed 2443 and my ngnix and phpfpm containers are linked. I would be able to connect to my socket server running on phpfpm container by going to telnet anonymous.com 2443
But its not getting connected. Here is the output
$ telnet anonymous.com 2443
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
Please note that previously when i had both nginx and php-fpm were on single container, every thing was working fine. So i am sure that there is nothing wrong with PHP. It just i cannot figure out how to access the socket server from outside world.
Thanks
Update
If i use my phpfpm container ip and use it with port 2443 through browser, its working fine. but the thing is i cannot rely on container ip as its all dynamic.
I had a similar issue (same output) using a socket server based on Ratchet. Mine was only a PHP container (= no nginx/apache/...).
It was because of the 3rd parameter given to the factory :
$server = IoServer::factory(
new HttpServer($webSocketServer), 2443, '127.0.0.1'
);
Removing 127.0.0.1 (and then use the default 0.0.0.0 value) solved the problem.
You should use the name of the service as the hostname. So to connect from nginx to phpfpm use phpfpm:2443
Related
I have two containers in a docker compose, a Postgres DB and a Symfony PHP app.
From within the backend-app (PHP Symfony) I would like to execute commands that handle the DB connection, but none of the configs I try seem to work.
I added expose (https://docs.docker.com/compose/compose-file/#expose) as hinted here and also added a default network as hinted here
docker-compose.yml
version: '3'
services:
database:
image: postgres:11
ports:
- 5431:5432
expose:
- "5431"
environment:
POSTGRES_PASSWORD: password
POSTGRES_USER: user
POSTGRES_DB: my_db
volumes:
- ./database:/var/lib/postgresql/data
frontend:
image: frontend-image:latest
ports:
- 8090:80
backend-app:
image: backend-app:latest
links:
- database
backend-web:
image: backend-web:latest
ports:
- 8091:80
depends_on:
- backend-app
- database
networks:
default:
Depending on the DB config in the Backend Container I get different error messages when executing php bin/console doctrine:schema:update --force inside backend-app:
DATABASE_URL="postgresql://user:password#database:5431/my_db?serverVersion=11&charset=utf8"
leads to
An exception occurred in driver: SQLSTATE[08006] [7] could not connect to server: Connection refused. Is the server running on host "database" (172.21.0.2) and accepting TCP/IP connections on port 5431?
and
DATABASE_URL="postgresql://user:password#localhost:5431/my_db?serverVersion=11&charset=utf8"
leads to
SQLSTATE[08006] [7] could not connect to server: Connection refused Is the server running on host "localhost" (127.0.0.1) and accepting TCP/IP connections on port 5431?
Where am I wrong in my approaches?
You don't get to choose what the container expose inside the internal docker network created by compose.
The postgress image exposes the port 5432, so your expose: 5431 instruction just exposes a port on which postgress is not listening, so it is useless.
So in between containers, you are stuck to using the port 5432 for postgress, unless you derive from the existing image, change the configuration there and expose the port you'd like.
The instruction below just change the port on which the container is exposed to the outside world, as pointed by the documentation
ports:
- 5431:5432
This means that you are exposing the port 5432 of the container to the port 5431 of your host.
Either specify both ports (HOST:CONTAINER), or just the container port (an ephemeral host port is chosen).
Source: https://docs.docker.com/compose/compose-file/#ports
To sum up:
your Symfony configuration should read:
DATABASE_URL="postgresql://user:password#database:5432/my_db?serverVersion=11&charset=utf8"
the expose directive in your compose file is useless
the ports directive as you wrote it there is only convenient if you want to connect from your host machine to the postgress container on a different port than the default one (i.e. because you already have a local postgress server running and, so the port is in use)
Our website-framework(s) are designed to work on both xampp and docker environments. We are recognizing our database hosts by host name/IP-address (dev, test, staging, live env). People who are working with xampp are using https://localhost, so they get the environment variable called Development. People who are working with docker are using https://docker as their host. They get the env-variable called Development/Docker. We need this differentiation because inside the php applications our xampp users are connecting to their mysql service with host localhost. Docker users have to connect via host called mysql (this is the container name of the mysql-service).
Because of the last occurred problems (not relevant to be mentioned here) we want a unique solution for both user-groups concerning the database connection: Docker users should be able to connect to their mysql service with host localhost.
docker-compose.yaml (shortened for better overview):
version: '2'
services:
#######################################
# PHP application Docker container
#######################################
app:
build:
context: .
dockerfile: Dockerfile.development
links:
- mail
- mysql
- redis
ports:
- "80:80"
- "443:443"
- "10022:22"
- "3307:3306"
volumes:
- ./app/:/app/
- ./:/docker/
cap_add:
- SYS_PTRACE
env_file:
- etc/environment.yml
- etc/environment.development.yml
environment:
- POSTFIX_RELAYHOST=[mail]:1025
#######################################
# MySQL server
#######################################
mysql:
build:
context: docker/mysql/
dockerfile: MariaDB-10.Dockerfile
ports:
- "3306"
volumes:
- mysql:/var/lib/mysql
env_file:
- etc/environment.yml
- etc/environment.development.yml
#######################################
# phpMyAdmin
#######################################
# /// #
#######################################
# Mail
#######################################
# /// #
#######################################
# Redis
#######################################
# /// #
# Volumes
volumes:
mysql:
phpmyadmin:
redis:
I tried a lot and played with the docker-compose but didn't find a solution for weeks. Tried with links, networks and so on. I think my docker skills are exhausted by now...
I also added to the mysql.conf:
bind-address = 0.0.0.0
Any ideas?
It is because of docker's networking structure.
docker creates 3 base interfaces. docker0 , host and none.
each container uses docker0 by default. then each container will have a virtual network interface for communicating between containers. so you can use your database with mysql address.
if you want to connect to database with address localhost you should config docker to use host network mode (you can do it by adding one line to defenition of your app service in docker compose file). it will be able to connect to every app which is running on your system. By the way you would loose communication with other container by their name. maybe you loose your connection with your redis (which is connected with redis address)
In this network mode, every dependency should be deployed or be exposed to your localhost.
I'm learning PDO now and I found it better to learn it in a LEMP docker stack (Nginx, php-fpm, MariaDB, phpMyadmin) on my Ubuntu 18.04LTS.
This is my php file:
<?php
try {
$mydb = new PDO('mysql:host=database;dbname=mysql;charset=utf8', 'root', 'admin');
} catch (Exception $e) {
die('Error : ' . $e->getMessage());
}
?>
As you can see, I try to make a PDO in my php code to recover some datas from my db.
But everytime I got that message on my browser (Firefox 69.0.2):
Error : could not find driver
I saw that post here: "Docker can't connect to mariadb with PHP". The problem was quite similar to mine but it didn't work for me.
Note: php-fmp and Nginx work perfeclty together. Same for MariaDB and phpMyAdmin.
Here is my docker-compose.yml file:
version: "3"
services:
nginx:
image: tutum/nginx
ports:
- "7050:80"
links:
- phpfpm
volumes:
- ./nginx/default:/etc/nginx/sites-available/default
- ./nginx/default:/etc/nginx/sites-enabled/default
- ./logs/nginx-error.log:/var/log/nginx/error.log
- ./logs/nginx-access.log:/var/log/nginx/access.log
phpfpm:
image: php:fpm
links:
- database:mysql
ports:
- "7051:9000"
volumes:
- ./public:/usr/share/nginx/html
database:
image: mariadb
environment:
MYSQL_ROOT_PASSWORD: admin
ports:
- "7052:3306"
phpmyadmin:
image: phpmyadmin/phpmyadmin
restart: always
links:
- database:mysql
ports:
- "7053:80"
environment:
PMA_HOST: mysql
PMA_USER: root
PMA_PASSWORD: admin
PMA_ARBITRARY: 1
If it is possible to solve this without building my own Dockerfiles, it would be great.
But if I must, I will. This isn't a problem.
docker-compose is an "api" of sorts for a Dockerfile. You need to add those libraries (apt-get etc...) in the Dockerfile
Dockerfile is your friend!
Is your PHP file inside a docker container or is it running outside docker, in the host machine?
If it is running inside the docker container, which service is it in? Please note that the nginx service does not have the "links" configuration, meaning it only accesses the database through the "database" hostname. Check the port as well (in the end of this post).
If your PHP file is running outside, then you have to use localhost instead of mysql in your connection string, like so: 'mysql:host=localhost;dbname=mysql;charset=utf8'. This is because docker's internal DNS is just that: internal. You can't access this hostname (database or mysql) outside docker.
Equally important, your connection string is not specifying the port, which is 7052 in your case. Since you're redirecting from 7052 to 3306, I think 3306 is mysql's default port, and the driver assumes 3306 if you do not specify it. It's always a good idea to be explicit about hosts and ports. Check the documentation on PHP databse connection strings about it (as I know nothing about php). It's probably ...;port=7052 or something.
Also, read up on docker-compose links, which you are using. It's deprecated now, so I advise to not use it in future projects, I even advise to spend some time removing it. Should take like 30 seconds to 5 minutes if everything goes well, and it won't haunt you anymore.
A found the solution.
First of all, the host must be mysql and not the name of my container (which is database):
$mydb = new PDO('mysql:host=mysql;dbname=mysql;charset=utf8', 'root', 'admin');
Inside the phpfpm container (accessible via the command docker-compose run --rm <container-name> bash), I had to enable the extension=php_pdo_msql line in my config file php.ini by removing the semicolon at the beginning of its line.
To avoid doing this manually every time after a docker-compose up, I replaced the phpfpm service in my docker-compose.yml file the following Dockerfile:
FROM php:fpm
RUN docker-php-ext-install pdo pdo_mysql
Finally, just build the image with the command docker-compose build . (replace the . by the path to the directory containing the docker-compose.yml file).
It works perfectly for me.
Sorry I am brand new to docker and web development in general but I made basic docker compose server that hosts my local PHP file and displays some text. It works fine with the local host but I bought some domains and was wondering how I change from connecting to localhost to a domain so anyone can connect to it. My IP is already set up for outside connect and works for my ssh server so I do not need to do that. I just can't seem to find any results when I try to look it up. So I just need to know what to change in my docker compose files or settings to make go a domain instead.
Here is my docker-compose file:
services:
product-service:
build: ./product
volumes:
- ./product:/usr/src/app
ports:
- 5001:80
website:
image: php:apache
volumes:
- ./website:/var/www/html
ports:
- 5000:80
depends_on:
- product-service
Without more knowledge about your code logic, I'm not sure if I can fully make it run just by this answer. But I guess I can give an abstract checklist.
Due to your docker-compose config, the port 5001, 5000 already being opened to localhost. If these ports are already configured to open to the external network, you can already type yourdomain.com:5000 to access it.
If you just want to access by typing yourdomain.com (without port). I assume your website service will serve it:
Open port 80 and connect it with port 80 of the website service:
website:
image: php:apache
volumes:
- ./website:/var/www/html
ports:
- 80:80
depends_on:
- product-service
Make sure any AJAX call to product-service API will be called to yourdomain.com:5001:
From inside the website service, it can call to product-serivce API by using localhost:5001. But from user browser, any AJAX call will be counted as external call, so any AJAX call to this service must be configure as yourdomain.com:5001
I am new to Docker.
I have read that it is better to keep an app per container.
I need to run web app (LAMP stack). So I have found the container for running PHP + Apache.
Now I need to set up a mysql container. But I am not sure what is the correct way to do that.
I read that it is possible to connect multiple containers together.
The idea is to make it trasnparent to the container running PHP + Apache when it tries to connect to mysql database locally.
But redirect all local connections to another container.
Another idea I have is to provide environment variable with host where should all connections go. In this case I need to have publicly accessible mysql server, but I need to keep it private and accessible only locally.
Could you please suggest a better option to choose in my case ?
Thank you
Use docker-compose:
For example, start from this docker-compose.yml. Put it in the same dir as your php Dockerfile:
version: "3"
services:
web:
build: .
ports:
- 8000:80
depends_on:
- db
db:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=something
volumes:
- ./mysql-data:/var/lib/mysql
Then:
docker-compose up
So thanks to Docker network, you can point from your PHP as this: db:3306.