2016-10-16 19 views
5

Używam Docker do tworzenia kontenera do testowania mojej aplikacji internetowej zbudowanej na PHP i MySQL na moim Macu. Moja aplikacja PHP jest zbudowana przy użyciu Fat-Free Framework dla MVC i routingu. Mam dwa pliki Docker, jeden dla MySQL i jeden dla PHP. Użyłem pomyślnie aplikacji testowych Docker, więc uważam, że moje obrazy są poprawnie zainstalowane.Korzystanie z Dockera Otrzymuję błąd: "SQLSTATE [HY000] [2002] Brak takiego pliku lub katalogu"

Główną częścią błędu:

Internal Server Error 

SQLSTATE[HY000] [2002] No such file or directory 

[fatfree/lib/DB/SQL.php:466] PDO->__construct('mysql:host=127.0.0.1;port=3306;dbname=robohome','root','password',array(1002=>'SET NAMES utf8;')) 
[fatfree/app/Controllers/Controller.php:24] DB\SQL->__construct('mysql:host=127.0.0.1;port=3306;dbname=robohome','root','password') 

Uwaga, jeśli mogę podłączyć używając 127.0.0.1 zamiast localhost mam nieco inny błąd, który mówi: SQLSTATE[HY000] [2002] Connection refused

My PHP Dockerfile:

FROM php:5.6-apache 

RUN docker-php-ext-install mysqli pdo pdo_mysql 
RUN a2enmod rewrite 

Mój plik MySQL Dockerfile:

FROM mysql:5.7 

ENV MYSQL_ROOT_PASSWORD password 
ENV MYSQL_DATABASE robohome 

COPY ./schema.sql /docker-entrypoint-initdb.d/ 

Mój plik Controller.php gdzie błąd wspomina linia 24:

<?php 

namespace Controllers; 

class Controller 
{ 
    protected $f3; 
    protected $db; 

    public function __construct() 
    { 
     $f3 = \Base::instance(); 
     $this->f3 = $f3; 

     $mysqlServerName = $f3->get("MYSQL_SERVERNAME"); 
     $mysqlDatabseName = $f3->get("MYSQL_DBNAME"); 

     //$container = \DI\ContainerBuilder::buildDevContainer(); <-Not used currently 

     //Below is line 24 referred to in the error 
     $db = new \DB\SQL(
      "mysql:host={$mysqlServerName};port=3306;dbname={$mysqlDatabseName}", 
      $f3->get("MYSQL_USERNAME"), 
      $f3->get("MYSQL_PASSWORD") 
     ); 

     $this->db = $db; 
    } 

Te wartości MYSQL_* są ściągane z .ini pliku:

MYSQL_SERVERNAME = "localhost" <-This is what I've tried changing to 127.0.0.1 
MYSQL_USERNAME = "root" 
MYSQL_PASSWORD = "password" 
MYSQL_DBNAME = "robohome" 

Moja Docker komponować pliku:

version: '2' 

services: 
    web: 
    build: ./docker/php 
    ports: 
     - 80:80 
    volumes: 
     - .:/var/www/html/ 
    links: 
     - db 
    db: 
    build: ./docker/mysql 
    ports: 
     - 3306 

Uruchamiam to wykonując docker-compose up --build -d. Wyjście mogę wtedy dostać od docker ps jest:

CONTAINER ID  IMAGE    COMMAND     CREATED    STATUS    PORTS      NAMES 
f35066a16586  robohomeweb_mysql "docker-entrypoint.sh" 3 minutes ago  Up 2 seconds  0.0.0.0:32777->3306/tcp robohomeweb_mysql_1 
86d34eb34583  robohomeweb_php  "apache2-foreground"  3 minutes ago  Up 2 seconds  0.0.0.0:80->80/tcp  robohomeweb_php_1 

Jeśli biegnę na pierwszym planie, a nie, pojawia się następujący komunikat:

Building php 
Step 1 : FROM php:5.6-apache 
---> 8f9b7e57129a 
Step 2 : RUN docker-php-ext-install mysqli pdo pdo_mysql 
---> Using cache 
---> fadd8f9e7207 
Step 3 : RUN a2enmod rewrite 
---> Using cache 
---> 9dfed7fdc60f 
Successfully built 9dfed7fdc60f 
Building mysql 
Step 1 : FROM mysql:5.7 
---> eda6a4884645 
Step 2 : ENV MYSQL_ROOT_PASSWORD password 
---> Using cache 
---> 759895ac5772 
Step 3 : ENV MYSQL_DATABASE robohome 
---> Using cache 
---> e926c5ecc088 
Step 4 : COPY ./schema.sql /docker-entrypoint-initdb.d/ 
---> Using cache 
---> cf5d00aa8020 
Successfully built cf5d00aa8020 
Starting robohomeweb_php_1 
Starting robohomeweb_mysql_1 
Attaching to robohomeweb_mysql_1, robohomeweb_php_1 
php_1 | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.3. Set the 'ServerName' directive globally to suppress this message 
php_1 | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.3. Set the 'ServerName' directive globally to suppress this message 
php_1 | [Sun Oct 16 20:21:17.944575 2016] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.10 (Debian) PHP/5.6.26 configured -- resuming normal operations 
php_1 | [Sun Oct 16 20:21:17.946919 2016] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND' 
mysql_1 | 2016-10-16T20:21:18.036272Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). 
mysql_1 | 2016-10-16T20:21:18.038330Z 0 [Note] mysqld (mysqld 5.7.16) starting as process 1 ... 
mysql_1 | 2016-10-16T20:21:18.043331Z 0 [Note] InnoDB: PUNCH HOLE support available 
mysql_1 | 2016-10-16T20:21:18.043603Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins 
mysql_1 | 2016-10-16T20:21:18.043951Z 0 [Note] InnoDB: Uses event mutexes 
mysql_1 | 2016-10-16T20:21:18.044077Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier 
mysql_1 | 2016-10-16T20:21:18.044260Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.3 
mysql_1 | 2016-10-16T20:21:18.044414Z 0 [Note] InnoDB: Using Linux native AIO 
mysql_1 | 2016-10-16T20:21:18.045150Z 0 [Note] InnoDB: Number of pools: 1 
mysql_1 | 2016-10-16T20:21:18.045620Z 0 [Note] InnoDB: Using CPU crc32 instructions 
mysql_1 | 2016-10-16T20:21:18.047629Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M 
mysql_1 | 2016-10-16T20:21:18.057705Z 0 [Note] InnoDB: Completed initialization of buffer pool 
mysql_1 | 2016-10-16T20:21:18.059988Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority(). 
mysql_1 | 2016-10-16T20:21:18.074670Z 0 [Note] InnoDB: Highest supported file format is Barracuda. 
mysql_1 | 2016-10-16T20:21:18.101209Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables 
mysql_1 | 2016-10-16T20:21:18.101433Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ... 
mysql_1 | 2016-10-16T20:21:18.354806Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB. 
mysql_1 | 2016-10-16T20:21:18.356928Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active. 
mysql_1 | 2016-10-16T20:21:18.357158Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active. 
mysql_1 | 2016-10-16T20:21:18.358049Z 0 [Note] InnoDB: Waiting for purge to start 
mysql_1 | 2016-10-16T20:21:18.412987Z 0 [Note] InnoDB: 5.7.16 started; log sequence number 12179647 
mysql_1 | 2016-10-16T20:21:18.414470Z 0 [Note] Plugin 'FEDERATED' is disabled. 
mysql_1 | 2016-10-16T20:21:18.421833Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool 
mysql_1 | 2016-10-16T20:21:18.424144Z 0 [Note] InnoDB: Buffer pool(s) load completed at 161016 20:21:18 
mysql_1 | 2016-10-16T20:21:18.425607Z 0 [Warning] Failed to set up SSL because of the following SSL library error: SSL context is not usable without certificate and private key 
mysql_1 | 2016-10-16T20:21:18.427018Z 0 [Note] Server hostname (bind-address): '*'; port: 3306 
mysql_1 | 2016-10-16T20:21:18.427581Z 0 [Note] IPv6 is available. 
mysql_1 | 2016-10-16T20:21:18.427749Z 0 [Note] - '::' resolves to '::'; 
mysql_1 | 2016-10-16T20:21:18.428019Z 0 [Note] Server socket created on IP: '::'. 
mysql_1 | 2016-10-16T20:21:18.456023Z 0 [Warning] 'db' entry 'sys [email protected]' ignored in --skip-name-resolve mode. 
mysql_1 | 2016-10-16T20:21:18.456354Z 0 [Warning] 'proxies_priv' entry '@ [email protected]' ignored in --skip-name-resolve mode. 
mysql_1 | 2016-10-16T20:21:18.480237Z 0 [Warning] 'tables_priv' entry 'sys_config [email protected]' ignored in --skip-name-resolve mode. 
mysql_1 | 2016-10-16T20:21:18.488758Z 0 [Note] Event Scheduler: Loaded 0 events 
mysql_1 | 2016-10-16T20:21:18.490880Z 0 [Note] mysqld: ready for connections. 
mysql_1 | Version: '5.7.16' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL) 

Z moich badań, próbowałem podłączenia przy użyciu zarówno localhost i 127.0.0.1, ponieważ są one technicznie traktowane inaczej. Może to być również coś związanego z próbą rozmowy przez gniazda zamiast TCP. Idealnie chciałbym znaleźć rozwiązanie, które mógłbym włożyć do moich plików Docker, więc nie muszę się martwić o zapamiętywanie komend lub jak coś zrobiłem.

+1

Co to jest zestaw mysql do słuchania? Port 3306 (domyślny dla TCP) lub plik gniazda? – Devon

+0

Na podstawie powyższego komentarza (musisz przewinąć w prawo, aby go zobaczyć) '0.0.0.0:32777-> 3306/tcp' – roundtheworld

+0

Edytowany w celu uwzględnienia mojego pliku komponentu Docker. – roundtheworld

Odpowiedz

24

Jak ktoś wskazał w komentarzach, podany przez ciebie plik dokowania jest bardzo istotny dla twojego pytania.

Dokumentacja links w plikach Döcker-komponować mówi

Containers for the linked service will be reachable at a hostname identical to the alias, or the service name if no alias was specified.

w Twoim przypadku, pojemnik bazy danych o nazwie db, więc rozwiązywania db hosta z pojemnika PHP powinien wskazać w pojemniku MySQL.Zastąpienie localhost z db w pliku konfiguracyjnym powinno pozwolić kontenerem PHP na połączenie z MySQL.

+1

To była informacja, której mi brakowało/nie rozumiałem; że lokalizacja mojej bazy danych musi pasować do jej nazwy w moim pliku dokowania. Mam to działa! – roundtheworld

+1

Chciałbym również dodać, że nie potrzebuję sekcji "links". Mój problem polegał w 100% na tym, że lokalizacja bazy danych w moim pliku konfiguracyjnym to 'localhost', kiedy powinna być nazwą mojej usługi w moim pliku yml' db'. – roundtheworld

+1

@roundtheworld To prawda, (całkiem) niedawno, Docker uzyskał wsparcie dla podstawowego [DNS] (https://docs.docker.com/engine/userguide/networking/default_network/configure-dns/), dzięki któremu kontenery mogą się nawzajem odnaleźć wg nazwy. – R0MANARMY

1

php działa na innym obrazie dokańczanym niż mySQL. zatem localhost i 127.0.0.1 z php nie wskazują na mysql. powinieneś połączyć się z ip instancji docker mysql.

Upewnij się również, że mysql nasłuchuje na wszystkich interfejsach. W mysql.ini musisz posłuchać 0.0.0.0, aby wysłuchać wszystkich dostępnych interfejsów. Domyślnie dozwolone są tylko połączenia z localhost (a kontener dockera php to inny host).

+1

Nie publikuj, chyba że potrzebujesz go gdzie indziej, po prostu innego punktu końcowego, który musisz zabezpieczyć. Połącz je ze sobą. https://docs.docker.com/compose/compose-file/#links – user2105103

+0

Rozumiem, że php i mysql żyją w różnych obrazach Docker, ale dla próbki znalezionej online, z której zbudowałem, nie widziałem niczego Zrobił to. Udało mi się przekonać ten przykład do działania, który jest bardzo podobny do mojego: https://github.com/mikesir87/docker-compose-demo – roundtheworld

+0

Zaktualizowałem odpowiedź. Łączenie kontenerów ze sobą jest tym, czego potrzebujesz, a następnie odniesienie za pomocą nazwy łącza. – user2105103