Connect to MariaDB with localhost from Docker container - php

First of I did read thoses links
Connect to Docker MySQL container from localhost?
Connect to Mysql on localhost from docker container
From inside of a Docker container, how do I connect to the localhost of the machine?
But as a beginner with docker. It did not help me.
What you need to know:
Yes, I need localhost. I'm working on an app that interact
directly with the database. It create/remove user privileges and
allow some user to access with limited privileges from a remote
access. When initialized, the app will drop the default remote access to root and forge user and grant them full privilege on localhost.
I'm using a docker-compose.yml generated by https://phpdocker.io
Ubuntu 18.10
Docker version 18.09.3, build 774a1f4
docker-compose version 1.21.0, build unknown
I'm using docker only for development purpose. On production I use forge
./docker-compose.yml
###############################################################################
# Generated on phpdocker.io #
###############################################################################
version: "3.1"
services:
mailhog:
image: mailhog/mailhog:latest
container_name: myapp-mailhog
ports:
- "8081:8025"
redis:
image: redis:alpine
container_name: myapp-redis
mariadb:
image: mariadb:10.4
container_name: myapp-mariadb
working_dir: /application
volumes:
- .:/application
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=myapp
- MYSQL_USER=forge
- MYSQL_PASSWORD=forge
ports:
- "8083:3306"
webserver:
image: nginx:alpine
container_name: myapp-webserver
working_dir: /application
volumes:
- .:/application
- ./phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- "8080:80"
php-fpm:
build: phpdocker/php-fpm
container_name: myapp-php-fpm
working_dir: /application
volumes:
- .:/application
- ./phpdocker/php-fpm/php-ini-overrides.ini:/etc/php/7.3/fpm/conf.d/99-overrides.ini
./phpdocker/nginx/nginx.conf
server {
listen 80 default;
client_max_body_size 108M;
access_log /var/log/nginx/application.access.log;
root /application/public;
index index.php;
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}
./phpdocker/php-fpm/Dockerfile (slightly modified to add mysql_client and not installing git in a second RUN command)
FROM phpdockerio/php73-fpm:latest
WORKDIR "/application"
# Fix debconf warnings upon build
ARG DEBIAN_FRONTEND=noninteractive
# Install selected extensions and other stuff
RUN apt-get update \
&& apt-get -y --no-install-recommends install \
php7.3-mysql php-redis php7.3-sqlite3 php-xdebug php7.3-bcmath php7.3-bz2 php7.3-gd \
git \
mysql-client \
&& apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
./php-ini-overrides.ini
upload_max_filesize = 100M
post_max_size = 108M
I tried to use network_mode: host but it makes the webserver stopping with Exit 1

Ok but as remember it, localhost in mysql/mariadb means access thru the local unix socket. There are ways of sharing these between containers.
Have a look here Connection between docker containers via UNIX sockets

#F.Maden gave me the right direction. I accepted his answer but here's how I made it in details.
Basically has he said, I need to share mysqld.sock between my services mariadb and php-fpm
The first step is to share a folder between both services. Since I already
have /application that contains the docker config /application/phpdocker, I will reuse this one.
I had to create a custom my.cnf file to edit the default mariadb config configuration and add a custom socket path:
./phpdocker/mariadb/my.cnf
[mysql]
socket = /application/phpdocker/shared/mysqld.sock
[mysqld]
socket = /application/phpdocker/shared/mysqld.sock
Then I had to share the config file with my mariadb container
./docker-compose.yml
mariadb:
image: mariadb:10.4
container_name: myapp-mariadb
working_dir: /application
volumes:
- .:/application
- ./phpdocker/mariadb/my.cnf:/etc/mysql/my.cnf # notice this line
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=myapp
- MYSQL_USER=forge
- MYSQL_PASSWORD=forge
ports:
- "8083:3306"
I created a folder ./phpdocker/shared with privileges 777 where mariadb will be able to create mysqld.sock (I couldn't start mariadb with 755. In my case this is only used on local not on production so it's fine)
From the terminal
$ mkdir ./phpdocker/shared && chmod 777 ./phpdocker/shared
And now test it!
From the terminal
$ docker-compose up -d --force-recreate --build
$ docker exec -it -u $(id -u):$(id -g) myapp-php-fpm /bin/bash
Once in the container
$ mysql -u root -p -h localhost --socket=/application/phpdocker/shared/mysqld.sock
$ mysql > select user();
+----------------+
| user() |
+----------------+
| root#localhost |
+----------------+

If the problem with connection to DB persists:
We can interogate what IP DB container has:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_name>
We'll receive container IP (eg: 172.21.0.3);
After this, we can place this IP into connection "host" section.
Enjoy!
Ref How can I access my docker maria db?

Related

SQLSTATE[HY000] [2002] Connection refused when trying to Dockerize Laravel App

I was able to access the mysql database from phpmyadmin using user: admin and password: root and the url: 127.0.0.1:3310 and I was able to load the website on 127.0.0.1:8008 but when i try to login or interact with the database i get the error below:
SQLSTATE[HY000] [2002] Connection refused
select * from users where email = boyiajas#gmail.com limit 1
and I also try to do a migration from within the app docker container but failed as well
root#58a709f18668:/var/www/html# php artisan migrate
Illuminate\Database\QueryException
SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = laravelvueblog_db and table_name = migrations and table_type = 'BASE TABLE')
below is my .env file
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3309
DB_DATABASE=laravelvueblog_db
DB_USERNAME=admin
DB_PASSWORD=root
below is my vhost.conf file
<VirtualHost *:8008>
DocumentRoot /var/www/html/public
<Directory "/var/www/html/public">
AllowOverride all
Require all granted
</Directory>
#ErrorLog ${APACHE_LOG_DIR}/error.log
#CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
below is my Docker file
FROM php:8-apache
USER root
RUN apt-get update -y && apt-get install -y openssl curl zip unzip git nano
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
RUN docker-php-ext-install mysqli pdo pdo_mysql opcache
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
WORKDIR /app
COPY . /app
COPY vhost.conf /etc/apache2/sites-available/000-default.conf
RUN chown -R www-data:www-data /app && a2enmod rewrite
RUN rm -rf /var/www/html && ln -s /app /var/www/html
RUN composer install
RUN php artisan optimize:clear
CMD php artisan serve --host=0.0.0.0 --port=8000
EXPOSE 8000
below is my docker-compose.yaml file
version: '3.8'
services:
db:
image: mariadb:latest
container_name: db
ports:
- 3309:3306
environment:
MYSQL_DATABASE: laravelvueblog_db
MYSQL_ROOT_PASSWORD: root
MYSQL_PASSWORD: root
MYSQL_USER: admin
volumes:
- mysql_file:/docker-entrypoint-initdb.d
networks:
- appnetwork
main:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/app
ports:
- 8008:8000
environment:
# MYSQL_DATABASE: laravelvueblog_db
# MYSQL_ROOT_PASSWORD: root
# MYSQL_PASSWORD: root
# MYSQL_USER: admin
DB_HOST: db
DB_USER: admin
DB_PASSWORD: root
DB_NAME: laravelvueblog_db
WAIT_HOSTS: db:3306
depends_on:
- db
links:
- db
networks:
- appnetwork
phpmyadmin:
image: phpmyadmin/phpmyadmin
ports:
- 3310:80
links:
- mysql
environment:
PMA_HOSTS: db
PMA_PORT: 3306
depends_on:
- db
networks:
- appnetwork
volumes:
mysql_file:
driver: local
networks:
appnetwork:
driver: bridge
After several attempt I found the problem, since all the services are on the same network (appnework)
I used the internal port in my laravel .env file like below
DB_PORT=3306
And now it works fine

Access index.php from docker

I've created a docker with a database and a php server but I'm failing accessing the php file from the server.
For testing purpose I'm currently having 2 index.php in my test app ./index.php and ./app/index.php
This is my docker-compose.yml
version: '3'
services:
symfony:
build:
context: .
dockerfile: docker/Dockerfile
image: project-manager
ports:
- 80:80
db:
image: mysql
ports:
- 3306:3306
volumes:
- "./.data/db:/var/lib/mysql"
environment:
MYSQL_ROOT_PASSWORD: root
phpmyadmin:
image: phpmyadmin/phpmyadmin
ports:
- "8080:80"
links:
- db
This is the php dockerfile
FROM php:7.4-fpm
# Install Composer
COPY --from=composer /usr/bin/composer /usr/bin/composer
# Copy all our files in the docker root
COPY . /
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f80a16af8336 project-manager "docker-php-entrypoi…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp, 9000/tcp project-manager_symfony_1
d97688010adf phpmyadmin/phpmyadmin "/docker-entrypoint.…" 9 minutes ago Up 9 minutes 0.0.0.0:8080->80/tcp project-manager_phpmyadmin_1
55781c004031 mysql "docker-entrypoint.s…" 9 minutes ago Up 9 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp project-manager_db_1
In my /etc/hosts
#Project Manager
127.0.0.1 project-manager.local
I can successfully access to the phpmyadmin using project-manager.local:8080
But if I try the simple project-manager.local/ or project-manager.local/index
I've got an empty response.
Root cause:
For symfony, you bind 80:80, this means you suppose there is a port 80 open in the php container. But, you use php:7.4-fpm which will just open port 9000.
(If you install net-tools in the container & use netstat -oanltp to check, there won't be 80 port open.)
Solutions:
Option 1:
If you insist to use php-fpm, then you need another web server container to pass the 80 request to php container's 9000 port. Maybe could add a more service with nginx container, and refers to connecting-nginx-to-php-fpm to set your configure for nginx container:
fastcgi_pass symfony:9000;
Option 2:
Switch to use php:7.4-apache, which defaults has a web server in the image open the 80 port, like next:
Dockerfile:
FROM php:7.4-apache
COPY . /var/www/html
index.php:
<?php
phpinfo();
NOTE: you should copy files to /var/www/html.
In a word, you should assure the container which you expose 80:80 really have a port 80 open in the container, otherwise, your expose is useless...

Docker, Symfony nginx/php-fpm initialized very slow

Using this project/Docker setup:
https://gitlab.com/martinpham/symfony-5-docker
When I do docker-compose up -d I have to wait about 2-3 minutes to actually get it working.
Before it loads, it gives me "502 Bad Gateway" and logs error:
2020/05/10 09:22:23 [error] 8#8: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.28.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://172.28.0.3:9000", host: "localhost"
Why nginx or php-fpm or smth else is loading so slow ?
It's my first time using nginx and Symfony. Is it something normal ? I expect it to be loaded max in 1-2 second, not 2-3 minutes.
Yes, I have seen similar issues, but not appropriate solutions for me.
Some nginx/php-fpm/docker-compose configuration should be changed - I tried, but no luck.
I modified a little bit nginx/sites/default.conf (just added xdebug stuff)
server {
listen 80 default_server;
#listen [::]:80 default_server ipv6only=on;
server_name localhost;
root /var/www/public;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_pass php-upstream;
fastcgi_index index.php;
fastcgi_buffers 4 256k;
fastcgi_buffer_size 128k;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#!!!!fixes timeouts
fastcgi_read_timeout 600;
include fastcgi_params;
fastcgi_param PHP_VALUE "xdebug.remote_autostart=1
xdebug.idekey=PHPSTORM
xdebug.remote_enable=1
xdebug.remote_port=9001
xdebug.remote_host=192.168.0.12";
}
location ~ /\.ht {
deny all;
}
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt/;
log_not_found off;
}
}
nginx/conf.d/default.conf:
upstream php-upstream {
server php-fpm:9000;
}
docker-compose.yml:
version: '3'
services:
database:
build:
context: ./database
environment:
- MYSQL_DATABASE=${DATABASE_NAME}
- MYSQL_USER=${DATABASE_USER}
- MYSQL_PASSWORD=${DATABASE_PASSWORD}
- MYSQL_ROOT_PASSWORD=${DATABASE_ROOT_PASSWORD}
ports:
- "3306:3306"
volumes:
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
- ./database/data:/var/lib/mysql
php-fpm:
build:
context: ./php-fpm
depends_on:
- database
environment:
- TIMEZONE=Europe/Tallinn
- APP_ENV=${APP_ENV}
- APP_SECRET=${APP_SECRET}
- DATABASE_URL=mysql://${DATABASE_USER}:${DATABASE_PASSWORD}#database:3306/${DATABASE_NAME}?serverVersion=5.7
volumes:
- ../src:/var/www
nginx:
build:
context: ./nginx
volumes:
- ../src:/var/www
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/sites/:/etc/nginx/sites-available
- ./nginx/conf.d/:/etc/nginx/conf.d
- ./logs:/var/log
depends_on:
- php-fpm
ports:
- "80:80"
- "443:443"
EDIT:
I think I know why now your project is taking ages to start. I had a closer look at the Dockerfile in the php-fpm folder and you have that command:
CMD composer install ; wait-for-it database:3306 -- bin/console doctrine:migrations:migrate ; php-fpm
As you can see, that command will install all composer dependencies and then wait until it can connect to the database container defined in the docker-compose.yml configuration :
services:
database:
build:
context: ./database
environment:
- MYSQL_DATABASE=${DATABASE_NAME}
- MYSQL_USER=${DATABASE_USER}
- MYSQL_PASSWORD=${DATABASE_PASSWORD}
- MYSQL_ROOT_PASSWORD=${DATABASE_ROOT_PASSWORD}
ports:
- "3306:3306"
volumes:
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
- ./database/data:/var/lib/mysql
Once the database is up and running, it will run the migration files in src/src/Migrations to update the database and then start php-fpm.
Until all of this is done, your project won't be ready and you will get the nice '502 Bad Gateway' error.
You can verify this and what's happening by running docker-compose up but omitting the -d argument this time so that you don't run in detached mode, and this will display all your container logs in real time.
You will see a bunch of logs, including the ones related to what composer is doing in the background, ex:
api-app | - Installing ocramius/package-versions (1.8.0): Downloading (100%)
api-app | - Installing symfony/flex (v1.6.3): Downloading (100%)
api-app |
api-app | Prefetching 141 packages
api-app | - Downloading (100%)
api-app |
api-app | - Installing symfony/polyfill-php73 (v1.16.0): Loading from cache
api-app | - Installing symfony/polyfill-mbstring (v1.16.0): Loading from cache
Composer install might take more or less time depending on whether you have all the repositories cached or not.
The solution here if you want to speed things up during your development would be remove the composer install command from the Dockerfile and run it manually only when you want to update/install new dependencies. This way, you avoid composer install to be run every time you run docker-compose up -d.
To do it manually, you would need to connect to your container and then run composer install manually or if you have composer directly installed in your OS, you could simply navigate to the src folder and run that same command.
This + the trick below should help you have a nice a fast enough project locally.
I have a similar configuration and everything is working well, the command docker-compose should take some time the first time you run it as your images need to be built, but then it shouldn't even take a second to run.
From what I see however, you have a lot of mounted volumes that could affect your performances. When I ran tests with nginx and Symfony on a Mac, I had really bad performances at the beginning with pages taking at least 30 seconds load.
One solution to speed this up in my case was to use the :delegated option on some of my volumes to speed up their access.
Try adding that options to your volumes and see if it changes anything for you:
[...]
volumes:
- ../src:/var/www:delegated
[...]
If delegated is not good option for you, read more about the other options consistent and cached here to see what would best fits your needs.

How to set up Apache2 and PHP-FPM via unix socket?

I try to set up Apache2 and PHP-FPM via unix socket but result is
(111)Connection refused: AH02454: FCGI: attempt to connect to Unix domain socket /run/php/php7.2-fpm.sock (*) failed
docker-compose.yml
version: "2"
services:
php:
build: "php:7.2-rc-alpine"
container_name: "php"
volumes:
- "./code:/usr/local/apache2/htdocs"
- "./php7.2-fpm.sock:/run/php/php7.2-fpm.sock"
apache2:
build: "httpd:2.4-alpine"
container_name: "apache2"
volumes:
- "./code:/usr/local/apache2/htdocs"
- "./php7.2-fpm.sock:/run/php/php7.2-fpm.sock"
ports:
- 80:80
links:
- php
www.conf
listen = /run/php/php7.2-fpm.sock
httpd-vhosts.conf
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php7.2-fpm.sock|fcgi://localhost/"
</FilesMatch>
But it's work when connect via TCP.
www.conf
listen = 127.0.0.1:9000
httpd-vhosts.conf
<FilesMatch \.php$>
SetHandler "proxy:fcgi://php:9000"
</FilesMatch>
Okie, so have the repo helped to fix the issue.
Issue #1 - www.conf being copied in apache container
You had below statement in your apache container Dockerfile
COPY ./www.conf /usr/local/etc/php-fpm.d/www.conf
This is actually intended for the php container which will be running php-fpm and not the apache container
Issue #2 - Socket was never being created
Your volume bind - "./php7.2-fpm.sock:/run/php/php7.2-fpm.sock" was creating the socket and they were not being created by php-fpm as such. So you created a blank file and trying to connect to it won't do anything
Issue #3 - No config in php to create socket
The docker container by default create listen to 0.0.0.0:9000 inside the fpm container. You needed to override the zz-docker.conf file inside the container to fix the issue.
zz-docker.conf
[global]
daemonize = no
[www]
listen = /run/php/php7.2-fpm.sock
listen.mode = 0666
Updated docker file
FROM php:7.2-rc-fpm-alpine
LABEL maintainer="Eakkapat Pattarathamrong (overbid#gmail.com)"
RUN docker-php-ext-install \
sockets
RUN set -x \
&& deluser www-data \
&& addgroup -g 500 -S www-data \
&& adduser -u 500 -D -S -G www-data www-data
COPY php-fpm.d /usr/local/etc/php-fpm.d/
Issue #4 - Sockets being shared as volumes to host
You should be sharing sockets using a named volume, so the socket should not be on host at all.
Updated docker-compose.yml
version: "2"
services:
php:
build: "./php"
container_name: "php"
volumes:
- "./code:/usr/local/apache2/htdocs"
- "phpsocket:/run/php"
apache2:
build: "./apache2"
container_name: "apache2"
volumes:
- "./code:/usr/local/apache2/htdocs"
- "phpsocket:/run/php"
ports:
- 7080:80
links:
- php
volumes:
phpsocket:
After fixing all the issues I was able to get the php page working

SSH in Docker container causes HTTP 404

I have such simple dockerfile for PHP:
# Base image
FROM php:7-fpm
# Update packages list
RUN apt-get --yes update;
# Install SSH server, set root password and allow root login
RUN apt-get --yes install openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:123' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# Run SSH server
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
And such docker-compose.yml file
web:
image: nginx:latest
volumes:
- /c/Users/marcin/dock-test/composers/l1.app/html/:/usr/share/nginx/html/
- /c/Users/marcin/dock-test/composers/l1.app/nginx/conf.d/:/etc/nginx/conf.d/
- /c/Users/marcin/dock-test/composers/l1.app/nginx/log/:/var/log/nginx/
ports:
- "8080:80"
working_dir: /usr/share/nginx/html/
links:
- php
- db
container_name: l1.web
environment:
- VIRTUAL_HOST=l1.app
php:
build: ../builds
dockerfile: Dockerfile-php7-fpm
volumes:
- /c/Users/marcin/dock-test/composers/l1.app/html/:/usr/share/nginx/html/
- /c/Users/marcin/dock-test/composers/l1.app/php/config/:/usr/local/etc/php/
working_dir: /usr/share/nginx/html/
links:
- db
container_name: l1.php
ports:
- "22020:22"
db:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=pass
- MYSQL_DATABASE=
- MYSQL_USER=
- MYSQL_PASSWORD=
expose:
- 3306
volumes:
- /c/Users/marcin/dock-test/composers/l1.app/mysql/data/:/var/lib/mysql/
- /c/Users/marcin/dock-test/composers/l1.app/mysql/conf.d/:/etc/mysql/conf.d/
- /c/Users/marcin/dock-test/composers/l1.app/mysql/log/:/var/log/mysql/
ports:
- "33060:3306"
container_name: l1.db
The problem - everything is working fine until I add in my dockerfile the last shown line:
CMD ["/usr/sbin/sshd", "-D"]
If I add this line, SSH is working fine but I'm getting 404 when displaying the page. When I comment this line, I'm getting page without a problem but obviously this SSH is not working.
What could be the problem with this? I just want to add I need this SSH service in PHP container (and running docker exec in this case is not an option)
The base image php-fpm ends with
CMD ["php-fpm"]
Your own CMD would override that (meaning php .
One workaround would be at least to ADD and call a wrapper script which would:
call php-fpm
launch sshd daemon
But that wouldn't play well with stop/kill signals, which would not stop everything. There are special images for managing more than one main process.
The OP Marcin Nabiałek confirms in the comments below:
I've created such file:
#!/bin/sh
# Start PHP
php-fpm -D
# Start SSH
/usr/sbin/sshd -D
and it seems to be working now without a problem.
A complete answer from #VonC and #Marcin Nabialek.
# php-fpm -D
# /usr/sbin/sshd -D
# use \n to make the content into multiple lines
RUN printf "php-fpm -D\n/usr/sbin/sshd -D" >> /start.sh
RUN chmod +x /start.sh
CMD ["/start.sh"]

Categories