Docker i Symfony 2.8 – budujemy kontener!

Jako, że przy ostatnim dockerowym poście znajomy zarzucił mi, że wpis był  bardzo nietechniczny, więc postanowiłem się poprawić i napisać o tym, jak tworzyłem kontener dockera, który odpali mi aplikację napisaną w Symfony 2.8.
A więc zaczynamy!

Pomysł był taki, aby na moim nowo skonfigurowanym serwerze uruchomić aplikację do obstawiania wyników meczów i udostępnić to w pracy. Aplikacja miałaby korzystać z istniejącej już bazy danych i dostać subdomenę w mojej głównej domenie, repo powinno oczywiście być zaciągane bezpośrednio z Bitbucketa, a jako, że aplikacja napisana jest w starej jak na tą chwilę wersji frameworka Symfony, bo wersji  2.8 to zapowiada się dość ciekawie.

Skoro już wiem co chcę zrobić, wypadałoby się zastanowić co jest potrzebne aby to uzyskać. Na pewno potrzebny będzie kontener z zainstalowanym systemem operacyjnym, php’em, wszystkimi niezbędnymi bibliotekami no i nginx’em. W sumie brzmi prosto i konkretnie.

W takim razie szybkie wyszukiwanie i znalazłem kontener z nginxem i phpem, na którym postanowiłem oprzeć swoje działanie:
https://github.com/TrafeX/docker-php-nginx

Jest to o tyle fajny obraz, że jeśli chcemy zmienić coś w konfiguracji php czy nginx’a, to wystarczy, że zmienimy to w plikach w katalogu config, a docker automatycznie nam to podepnie.

Dockerfile składa się z kilku części, czyli listy paczek, które chcemy zainstalować, konfiguracji nginxa i php-fpma oraz zmian dotyczących folderów i użytkowników.

Na pierwszy ogień poszła sekcja z paczkami, czyli tym, czego potrzebujemy.
Brakowało nam phpowej biblioteki do obsługi MySQLa, oraz do zarządzania uprawnieniami, więc należało je dodać

#Install packages
RUN apk --no-cache add php7 php7-fpm php7-mysqli php7-json php7-openssl php7-curl \
php7-zlib php7-xml php7-phar php7-intl php7-dom php7-xmlreader php7-ctype \php7-mbstring php7-gd nginx supervisor curl php-pdo php7-simplexml php7-xmlwriter \
php7-tokenizer php7-redis php7-xsl php7-pdo_mysql php7-mysqlnd php7-pcntl \
php7-iconv php7-posix acl

Kolejne rzeczy, które okazały się przydatne to git oraz composer

#git
RUN apk update apk upgrade && apk add --no-cache bash git openssh
#composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

Po instalacji których przygotujemy nasze środowisko, czyli stworzymy katalog na logi oraz katalog na naszą aplikację

RUN mkdir -p /opt/nginx/logs/
RUN mkdir -p /var/www/

Po uporaniu się z tym jakże trudnym zadaniem możemy przejść do katalogu, gdzie będziemy trzymać aplikację i ściągnąć tam nasze repo

WORKDIR /var/www/
RUN git clone https://user:passwd@bitbucket.org/user/repo.git

I tutaj na chwilę się zatrzymam. Jak wszyscy dobrze wiemy, w repo nie przechowuje się haseł do aplikacji ani innych czułych rzeczy, więc muszę stworzyć potrzebny do konfiguracji pliku parameters.yml, w którym przechowam SecretKey na podstawie którego symfony tworzy sesje oraz co istotniejsze hasła do bazy danych.
Żeby było wygodniej nie tworzę tego pliku w kontenerze, a w katalogu src hosta, dzięki czemu mogę jego istnienie oddzielić od kontenera, przechowywać go w bezpiecznym repo, albo po prostu na serwerze. Plik ten po ściągnięciu repozytorium kopiuję do odpowiedniego katalogu.

WORKDIR /var/www/bettolose/
COPY src /var/www/bettolose/app/config/

A następnie odpalam composera, który dociągnie zależności do aplikacji

RUN SYMFONY_ENV=prod composer install --no-dev --optimize-autoloader

W tym momencie mam prawie wszystko gotowe i jestem krok od zbudowania poprawnego obrazu, jednak dotarłem do momentu, w którym muszę nadać odpowiednie uprawnienia dla folderów z logami. Tutaj spędziłem największą ilość czasu, bo rozwiązania z dokumentacji nie do końca działały, ale udało mi się stworzyć może nie do końca poprawny skrypt, który rozwiązywał problem

RUN rm -rf app/logs/*
RUN rm -rf app/cache/*
RUN HTTPDUSER=$(ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\  -f1)
RUN setfacl -dR -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX app/cache app/logs
RUN setfacl -R -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX app/cache app/logs
RUN php app/console cache:clear --env=prod --no-debug
RUN chmod a+w -R app/logs/<br>RUN chmod a+w -R app/cache/

Teraz wystarczy zalogować się na VPSa i zbudować obraz kontenera na podstawie pliku Dockerfile, robimy to wydając komendę:

docker build -t "bets" .     

Osobiście używam docker-compose do zarządzania tym, co mam na VPSie, więc kolejnym krokiem będzie dodanie odpowiedniego wpisu do pliku docker-compose.yml
Widać w nim, że aplikacja jest zależna od mysqla oraz, że traefik dba o odpowiednie przypisanie subdomeny dla niej.

  mpbetsapp:
     image:  bets 
     container_name: bets-app
     restart: always
     networks:
       - myNetwork
     depends_on:
       - mysql
     labels:
       - "traefik.frontend.rule=Host:bets.myhost.pl"
       - "traefik.port=80"
       - "traefik.docker.network=myNetwork"
       - "traefik.enable=true"

Tak skonfigurowany plik wystarczy uruchomić poleceniem „up” z opcją „–d”, aby całość procesu działa się w tle.

docker-compose up -d

I w taki oto prosty sposób w mniej niż dwie godziny mamy gotowy kontener dockera z działającą i wystawioną na świat aplikacją do typowania wyników wydarzeń sportowych napisaną w Symfony 2.8. Jeśli ktoś chciałby pełny kod Dockerfile dostepny jest w moim repo githubowym, dostępnym pod adresem:
https://github.com/piszu/nginx-php-fpm

Jeśli w jakiś sposób przydał Ci się ten artykuł – zostaw komentarz! 🙂

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *