Slide 1

Slide 1 text

Docker for PHP developers Tips, Tricks & Lessons learned PhpPrague 2018 Vladimír Kriška @ujovlado

Slide 2

Slide 2 text

whoami Programmer (mostly PHP, but also JS) Developer at Keboola building ETL platform Keboola Connection writing about it at 500.keboola.com technologies: // TODO insert cool words here twitter.com/ujovlado ujovlado.com medium.com/@ujovlado 2

Slide 3

Slide 3 text

How I started with Docker? I was in a mood to get rid of "host installations" I was playing with Vagrant and default setup was too slow for me 3

Slide 4

Slide 4 text

Proof 4

Slide 5

Slide 5 text

Now I want everyone to use Docker 5

Slide 6

Slide 6 text

Past 6

Slide 7

Slide 7 text

Past New computer Install Apache/Nginx, MySQL/PostgreSQL, PHP, MongoDB, etc. Start services, start coding After few weeks: OMG, this project needs different version of MySQL and PHP ... Problems (vedle pasti) 7

Slide 8

Slide 8 text

Future New computer Prepare Docker le, build services Run them, start coding After few weeks: OMG, this project needs different version of MySQL and PHP ... Never mind, I'll add or update services and rebuild images 8

Slide 9

Slide 9 text

Tips & tricks 9

Slide 10

Slide 10 text

Docker Compose Must have for development docker-compose up my-app docker-compose run --rm my-app bash Very good for testing docker-compose run --rm my-app ./vendor/bin/phpunit 1. docker-compose up -d 2. run tests 3. docker-compose down 10

Slide 11

Slide 11 text

Example (development) services: my-app: build: . volumes: - ./:/code working_dir: /code ports: - "4321:80" command: bash tty: true 11

Slide 12

Slide 12 text

Example (testing, CI) services: - docker script: - ... - docker-compose up -d udp-listener - php tests/run.php - docker-compose logs udp-listener | grep 'Some text' 12

Slide 13

Slide 13 text

Images with option to run sh/bash instantly Very handy for debugging Easier than overriding entrypoint Just append what you need to run This is very easy: docker run -i -t --rm debian bash Shouldn't we prepare every service like this? 13

Slide 14

Slide 14 text

Example docker-compose run --rm my-app composer install docker-compose run --rm my-app ./cli.php migrations:migrate or just: docker-compose run --rm my-app bash to enter container and play inside 14

Slide 15

Slide 15 text

Run common CLI commands in Docker Don't install php locally, you have containers Don't install tools like travis CLI localy Prepare images and run commands in container to keep your host system clean If you need something, then mount volume Remember that your PC is only a resource 15

Slide 16

Slide 16 text

Example (part 1) FROM ruby:2 RUN gem install travis -v 1.8.2 --no-rdoc --no-ri ARG USER_NAME ARG USER_UID ARG USER_GID RUN groupadd --gid $USER_GID $USER_NAME RUN useradd --uid $USER_UID --gid $USER_GID $USER_NAME ENTRYPOINT ["travis"] $ docker build -t travis \ --build-arg USER_UID=`id -u` \ --build-arg USER_GID=`id -g` \ --build-arg USER_NAME=`id -un` \ . 16

Slide 17

Slide 17 text

Example (part 2) #!/bin/bash docker run -i -t --rm \ -v "/home/vlado/workspace/travis-cli/.travis :/home/`id -un`/.travis" \ -v "$PWD:$PWD" \ -w $PWD \ -u `id -u` \ travis "$@" Magic here is volumes section and $@ which will proxy all passed args to container 17

Slide 18

Slide 18 text

Everything is le and can be mounted as volume You want to log something using syslog Hey, but there's no syslog running in my container Let's create new service to provide syslog for me 18

Slide 19

Slide 19 text

Example (part 1) services: syslog: build: docker/syslog volumes: - ./docker/.syslog-datadir/socket:/syslog-socket - ./docker/.syslog-datadir/log:/var/log syslog-watcher: image: debian:8 volumes_from: - syslog command: tail -f /var/log/syslog 19

Slide 20

Slide 20 text

Example (part 2) services: my-app: image: debian volumes: - ./docker/.syslog-datadir/socket/log:/dev/log links: - syslog command: bash now you can log to syslog and will see logs using "watcher" service 20

Slide 21

Slide 21 text

Docker in Docker (almost) Very similar to syslog part, but we mount Docker socket With mounted socket, container has access to Docker on host machine So you can have application running in container and executing commands like docker run in container 21

Slide 22

Slide 22 text

Example docker run -i -t docker sh -c 'docker ps -q' Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? docker run -i -t \ -v /var/run/docker.sock:/var/run/docker.sock \ docker \ sh -c 'docker ps -q' 5a11cca86782 22

Slide 23

Slide 23 text

Lessons learned 23

Slide 24

Slide 24 text

It's easier to start with Apache than with Nginx Apache only needs vhost con guration and php.ini -> 1 service Nginx needs the same plus php-fpm -> 2 services So if you don't care, use Apache. 24

Slide 25

Slide 25 text

Do not run database in containers Databases are critical to your businness You probably won't get it right (me neither) How would you solve: backups? replication? Probably the best is: buy database as a service (AWS RDS, etc.) have databases server (managed by someone) 25

Slide 26

Slide 26 text

Same image for development and production environment Only difference should be the code and environment variables composer install should be run during image build On localhost, it'll load all dependencies from cache Code should be copied in image On localhost override code with volume Test should run in container 26

Slide 27

Slide 27 text

One Docker image to rule them all If more programs need your PHP code, it's better to add all these programs to one image. And than only change program to run. Apache: FROM php:7-apache (this can be default service) Cron: RUN apt-get instal cron (to run, override command to cron -f ) PHP CLI: already in Apache image (to run, override command to php some-script.php ) 27

Slide 28

Slide 28 text

Custom PHP builds Try to avoid building PHP (use FROM php:7 , not apt-get install php7-cli and similar) For extensions use docker-php-ext-install Do not reinvent a wheel - there's a big community behind of cial images Of cial images are based on Debian - very common and stable distribution Alpine is smaller, but can cause problems (we had one - with memory) 28

Slide 29

Slide 29 text

Do not try to enter the container It looks real but with bigger amount of containers starting/stopping it's almost impossible You probably only need logs, so send them to stdout If you need some les from container, use volume or send them to S3 Run another service with mounted Docker socket to collect these logs Use logspout to forward logs to 3rd party service like Papertrail 29

Slide 30

Slide 30 text

How to enter the container To running container with your service (not recommended): docker exec -i -t 5a11cca86782 - it's very dangerous, because executing "wrong" commands can kill whole container If you really need to chcek what's going on - e.g. to be in same environment, just start one container with long running process - e.g. tail -f /xyz . Then docker exec to this container and play. 30

Slide 31

Slide 31 text

Live coding? 31

Slide 32

Slide 32 text

32

Slide 33

Slide 33 text

Questions? 33

Slide 34

Slide 34 text

Thank you!