3

First of I did read thoses links

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

Clément Baconnier
  • 5,718
  • 5
  • 29
  • 55
  • Where does the constraint that it _must_ be `localhost` come from? – David Maze Mar 13 '19 at 14:06
  • So what you are saying is that you need access to mysql thru the local unix socket and you will not allow access true TCP/IP? Guess that is what localhost means in MariaDB – F.Madsen Mar 13 '19 at 14:17
  • @DavidMaze The PHP (Laravel project) I'm working on as migration files that setup the database. It executes SQL that create a `root@localhost`, `forge@localhost`, delete `root@%` and revoke/grant privileges on `forge@%` and during the application lifecycle, it will create, drop users etc.. The reason we drop access to `%` is because your clients need a readable remote access on some views. But we don't want users with high privilege to be accessible from remote. – Clément Baconnier Mar 13 '19 at 14:17
  • @F.Madsen From **webserver** I need to connect to **mariadb** with `mysql -u root -h localhost -p` and `mysql -u forge -h localhost -p` – Clément Baconnier Mar 13 '19 at 14:19

3 Answers3

2

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.Madsen
  • 702
  • 4
  • 6
  • Thanks! But how does it work with docker-compose? Here's what I tried: `docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock busybox` in an another terminal: `docker-compose up -d` then `docker exec -it -u $(id -u):$(id -g) myapp-php-fpm /bin/bash` and finally in the container `mysql -u root -h localhost -p` but I got `ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)` – Clément Baconnier Mar 13 '19 at 14:42
  • I also tried to replace `/var/run/docker.sock:/var/run/docker.sock` with `/var/run/mysqld/mysqld.sock:/var/mysqld/mysqld.sock` with no success. (Sorry, I'm not familiar at all with docker) – Clément Baconnier Mar 13 '19 at 14:44
  • 1
    Then it'll not be easy... Basicly you need to create a folder on your local host that will hold the socket-file. Then you mount this folder in both the mariadb and the web container. That will be in the "volumes:" sections of your compose yml file. Doing so, you will effectively create the db socket on you local filesystem. Also make sure that the privileges on the socket is right. – F.Madsen Mar 13 '19 at 15:00
  • I make it works! Thank you very much! I will make an additional answer on how exactly I did it. – Clément Baconnier Mar 13 '19 at 16:12
  • 1
    Great, if you are nice to the docker whale, it'll be nice to you :) – F.Madsen Mar 13 '19 at 16:13
  • Is it possible to archive the same with `networks`? I really don't want to store the socked on my host. There must be a way to tell docker to expose mariadb to php's localhost. It's just a different port. – muuvmuuv Jun 25 '19 at 12:18
0

@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

  1. 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.

  2. 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
  1. 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"
  1. 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 |
+----------------+
Clément Baconnier
  • 5,718
  • 5
  • 29
  • 55
  • 1
    Great and clear description. You can avoid the 777 privilege problem by creating a unix group, eg. dockergrp with a specific GID. X . Then you do the same in all your images and make sure the users created in the containers are granted a group with a GID X. unix/linux is special while it does not care about the name of a group, only the GID. Now 770 is enough. The same group can be used generally for all containers running. – F.Madsen Mar 14 '19 at 10:02
  • @F.Madsen Thanks for the tip! I will definitely make that. I have learned at LOT on docker with that question and now you're already answering me what the next question I had in mind. Again, Thank you very much! – Clément Baconnier Mar 14 '19 at 10:12
0

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?

LucianDex
  • 469
  • 2
  • 12