docker for developers - php[tek] 2017

175
Docker for PHP Developers Chris Tankersley @dragonmantank php[tek] 2017 php[tek] 2017 1

Upload: chris-tankersley

Post on 28-Jan-2018

291 views

Category:

Technology


6 download

TRANSCRIPT

Docker for PHP DevelopersChris Tankersley

@dragonmantank

php[tek] 2017

php[tek] 2017 1

php[tek] 2017

Secret Docker Wifi

3

● SSID: phptek_docker● Password: phpdocker2017

● NAS: 172.16.0.40● Username: admin● Password: secretpassword

php[tek] 2017

What Is Docker?

“Docker is an open platform for developers and sysadmins to build, ship, and run distributed applications. Consisting of Docker Engine, a portable, lightweight runtime and packaging tool, and Docker Hub, a cloud service for sharing applications and automating workflows, Docker enables apps to be quickly assembled from components and eliminates the friction between development, QA, and production environments.”

4

https://www.docker.com/whatisdocker/

php[tek] 2017

What is a Container?

5

php[tek] 2017

Normal Bare-Metal Server

6

CPU RAM HD Network

Operating System

nginx PHP DB

CPU RAM I/O0

5

10

15

20

25

% Resources

php[tek] 2017

Normal Bare-Metal Server

7

CPU RAM HD Network

Operating System

nginx PHP DB

CPU RAM I/O0

5

10

15

20

25

30

35

App Resources

% Resources

php[tek] 2017

Virtual Machines

8

CPU RAM HD Network

Operating System

nginx PHP DB

Operating System

nginx PHP DB

Operating System

Hypervisor

CPU RAM I/O0

10

20

30

40

50

60

70

App Resources

% Resources

php[tek] 2017

Containers

9

CPU RAM HD Network

Operating System

nginxnginx PHP DB PHP DB

CPU RAM I/O0

5

10

15

20

25

30

35

40

45

App Resources

% Resources

php[tek] 2017

Containers vs VMs

CPU RAM I/O0

10

20

30

40

50

60

70

App Resources

% Resources

CPU RAM I/O0

5

10

15

20

25

30

35

40

45

App Resources

% Resources

php[tek] 2017

Containers Are Not New

• LXC (Linux Containers)• OpenVZ• Systemd-nspawn• BSD Jails• Solaris Zones• chroot

11

php[tek] 2017

Containers are just walled processes

12

Ubuntu Kernel

/+ bin/+ etc/+ dev/+ home/+ usr/+ var/+ lib/+ …

nginx

bash

/+ bin/+ etc/+ dev/+ home/+ usr/+ var/+ lib/+ …

php

php[tek] 2017

What is Docker?

13

php[tek] 2017

Docker is an Ecosystem

14

Docker Engine

php[tek] 2017

Docker is an Ecosystem

15

Docker ComposeDocker Machine Docker Swarm

php[tek] 2017

How does it work?

16

Uses a variety of existingContainer technologies

Server ContainersHyper-V Containers xhyve Virtualization

php[tek] 2017

Sorry OSX < 10.10 and Windows < 10 Users

Docker Toolbox

17

php[tek] 2017

Let’s use Docker

18

php[tek] 2017

Running a container

• `docker run` will run a container• This will not restart an existing container, just create a new one• docker run [options] IMAGE [command] [arguments]

• [options ]modify the docker process for this container• IMAGE is the image to use• [command] is the command to run inside the container• [arguments] are arguments for the command

19

php[tek] 2017

Running a simple shell

20

php[tek] 2017

Running a simple shell

21

php[tek] 2017

Running a simple shell

22

php[tek] 2017

What’s Going On?

23

Ubuntu Kernel

/+ bin/+ etc/+ dev/+ home/+ usr/+ var/+ lib/+ …

nginx

bash

/+ bin/+ etc/+ dev/+ home/+ usr/+ var/+ lib/+ …

php

php[tek] 2017

Running Two Webservers

24

php[tek] 2017

Running Two Webservers

25

php[tek] 2017

Running Two Webservers

26

php[tek] 2017

Running Two Webservers

27

php[tek] 2017

Running Two Webservers

28

php[tek] 2017

Running Two Webservers

29

php[tek] 2017

Running Two Webservers

30

php[tek] 2017

Running Two Webservers

31

php[tek] 2017

Some Notes

• All three containers are 100% self contained• Docker containers share common ancestors, but keep their own files• `docker run` parameters:

• --rm – Destroy a container once it exits• -d – Run in the background (daemon mode)• -i – Run in interactive mode• --name – Give the container a name• -p [local port]:[container port] – Forward the local port to the container port

32

php[tek] 2017

Volumes

33

php[tek] 2017

Modifying a running container

• `docker exec` can run a command inside of an existing container• Use Volumes to share data

34

php[tek] 2017

Persistent Data with Volumes

• You can designate a volume with –v• Create a named volume with `volume create`• Volumes can be shared amongst containers• Volumes can mount data from the host system

35

php[tek] 2017

Mounting from the host machine

36

php[tek] 2017

Mounting from the host machine

37

php[tek] 2017

Mounting from the host machine

38

php[tek] 2017

Mounting from the host machine

39

php[tek] 2017

Mounting from the host machine

40

php[tek] 2017

Mounting from the host isn’t perfect

• The container now has a window into your host machine• Permissions can get screwy if you are modifying in the container

• Most things it creates will be root by default, and you probably aren’t root on the host machine

• Host-mounted volumes are not portable at all• OSX and Hyper-V VMs have limited pathings to mount• OSX has poor I/O performance

41

php[tek] 2017

Named Data Volumes

• Creates a space that becomes persistent• Can be mounted anywhere inside your images• Have our app containers use the data volume to store data• Use ‘editor containers’ to go in and modify data when needed

42

php[tek] 2017

vim Tutorial

• vim is a Modal text editor• ESC will drop you back to default mode• :new /opt/webconfig/default to create a new file• In default mode, i will get us into interactive (edit) mode• :w to save a file• :q will quit

43

php[tek] 2017

Mounting Data Volumes

44

php[tek] 2017

Mounting Data Volumes

45

php[tek] 2017

Mounting Data Volumes

46

php[tek] 2017

Mounting Data Volumes

47

php[tek] 2017

Mounting Data Volumes

48

php[tek] 2017

Mounting Data Volumes

49

php[tek] 2017

Why go through the hassle?

• Data volumes are portable, depending on the driver• Data volumes are safer• Separates the app containers from data• Production can use a data volume, dev can use a host volume

• Our app containers stay small• Works directly with other tools

50

php[tek] 2017

Networking

51

php[tek] 2017

Networking

• Docker can create multiple network “pools”• Each container gets an IP address• Containers can be attached to multiple networks• Docker network allow service discovery inside networks

52

php[tek] 2017

Legacy - Docker Links

• Legacy Links work with `--link`• Only works on the legacy “bridge” network• Doesn’t support service discovery

• Not worth it to use anymore

53

php[tek] 2017

Docker Networks

• Discreet IP pool for containers• Containers can be added and removed to the network at whim• Service discovery though ‘--network-alias’• Can be set up to work across hosts

54

php[tek] 2017

Create a network

55

php[tek] 2017

Attach to a network

56

php[tek] 2017

Ping the web container

57

php[tek] 2017

Add another web and kill web1

58

php[tek] 2017

BREAK TIME! WOO!

59

php[tek] 2017

Other Helpful Commands

60

php[tek] 2017

Inspect a container

docker inspect [options] CONTAINER_NAME

• Returns a JSON string with data about the container• Can also query• docker inspect -f “{{ .NetworkSettings.IPAddress }}” web_server

• Really handy for scripting out things like reverse proxies

61

php[tek] 2017

Work with images

• docker pull IMAGE – Pulls down an image before using• docker images – Lists all the images that are downloaded• docker rmi IMAGE – Deletes an image if it’s not being used

62

php[tek] 2017

Containerizing An Application

63

php[tek] 2017

Our Goals

• Not change our workflow (much)• Run PHP 7, Unit Tests, and webserver• Deploy “easily”

64

php[tek] 2017

Just try and run it

docker run -d --name d4dapp \

-v C:\drago\Projects\dockerfordevs-app:/var/www/ \

-p 8080:80

php:apache

65

php[tek] 2017 66

php[tek] 2017

Checking Logs

• Containers log to stdout/stderr• Docker aggregates the logs• Can be viewed with docker logs

67

php[tek] 2017

Oops

68

php[tek] 2017

Custom Images

• PHP images are pretty bare• Lots of times need to install extensions

69

php[tek] 2017

Dockerfile

• Dockerfile is the configuration steps for an image• Can be created from scratch, or based on another image• Allows you to add files, create default volumes, ports, etc• Can be used privately or pushed to Docker Hub

70

php[tek] 2017

docker/Dockerfile

FROM php:apache

RUN a2enmod rewrite

71

php[tek] 2017

Build it

docker build -t tag_name ./

• This runs through the Dockerfile and generates the image• We can now use the tag name to run the image

72

php[tek] 2017

Build it

docker build -t d4dapp docker/

73

php[tek] 2017 74

php[tek] 2017

Use the new image

docker run -d --name d4dapp \

-v C:\drago\Projects\dockerfordevs-app:/var/www/ \

-p 8080:80

d4dapp

75

php[tek] 2017

Use the new image

76

php[tek] 2017

Slightly better

77

php[tek] 2017

Install Dependencies

78

php[tek] 2017

Running Composer

docker run --rm \

-v c:/Users/drago/.composer:/root/.composer \

-v c:/Users/drago/Projects/workshop:/app \

-v c:/Users/drago/.ssh:/root/.ssh \

composer/composer \

install

79

php[tek] 2017

Better!

80

php[tek] 2017

Look at queues!

81

php[tek] 2017

docker/Dockerfile

FROM php:apache

RUN a2enmod rewrite\

&& docker-php-ext-install pdo_mysql

82

php[tek] 2017

Rebuild the image

docker build -t d4dapp docker/

83

php[tek] 2017

Rebuild the container

$ docker rm -f d4dapp

$ docker run -d --name d4dapp \

-v C:\drago\Projects\dockerfordevs-app:/var/www/ \

-p 8080:80

d4dapp

84

php[tek] 2017

Progress!

85

php[tek] 2017

Docker Compose

86

php[tek] 2017

What is Docker Compose?

• Multi-container orchestration• A single config file holds all of your container info• Works with Docker Swarm and a few other tools, like Rancher

87

php[tek] 2017

Sample docker-compose.ymlversion: '2'

volumes: mysqldata: driver: local

services: d4dapp: build: ./docker/ volumes: - ./:/var/www/ ports: - 8080:80

mysqlserver: image: mysql environment: MYSQL_DATABASE: dockerfordevs MYSQL_ROOT_PASSWORD: 's3curep@assword' volumes: - mysqldata:/var/lib/mysql

88

php[tek] 2017

No longer use docker run

$ docker rm –f d4dapp

$ docker-compose up -d

89

php[tek] 2017

Now we have 2 containers

90

php[tek] 2017

Config for DB now points to the service name

91

<?php

return [ 'debug' => true,

'config_cache_enabled' => false,

'db' => [ 'driver' => 'Pdo_Mysql', 'hostname' => 'mysqlserver', 'port' => '3306', 'database' => 'dockerfordevs', 'user' => 'root', 'password' => 's3curep@assword', ],];

php[tek] 2017

Yay!

92

php[tek] 2017

Install our DB Migration Software

docker run --rm \

-v c:/Users/drago/.composer:/root/.composer \

-v c:/Users/drago/Projects/workshop:/app \

-v c:/Users/drago/.ssh:/root/.ssh \

composer/composer \

require robmorgan/phinx

93

php[tek] 2017

Set up phinx

docker run --rm \

-v C:\Users\drago\Projects\dockerfordevs-app\:/app \

-w /app \

php:cli php vendor/bin/phinx init

94

php[tek] 2017

Run the migration

docker run --rm \

-v C:\Users\drago\Projects\dockerfordevs-app\:/app \

-w /app \

--network dockerfordevsapp_default \

php:cli php vendor/bin/phinx migrate

95

php[tek] 2017

Oops

96

php[tek] 2017

Let’s use the existing container

docker-compose run --rm \

-v C:\Users\drago\Projects\dockerfordevs-app\:/app \

-w /app \

d4dapp php vendor/bin/phinx migrate

97

php[tek] 2017

Good…

98

php[tek] 2017

It Lives!

99

php[tek] 2017

Unit Testing

docker run --rm \

-v C:\Users\drago\Projects\dockerfordevs-app\:/app \

-w /app \

d4dapp php vendor/bin/phpunit -c .

100

php[tek] 2017

Running the tests

php[tek] 2017

Build a service

service:

testrunner:

build: ./docker/

volumes:

- ./:/app

working_dir: /app

command: vendor/bin/phpunit -c .

102

php[tek] 2017

Run the tests with the service

docker-compose run --rm testrunner

103

php[tek] 2017

Running the tests

Docker Machine

ZendCon, October 2016 105

What is Docker Machine?

• A provisioning tool that is used to set up a box with Docker• Used in Docker Toolbox to create the VM• Supports:• EC2• Azure• Digital Ocean• Hyper-V• OpenStack• Virtualbox• VMWare

php[tek] 2017 106

Why use it?

• Makes it very easy to spin up new boxes• Docker Machine handles all of the dirty stuff for you• Docker Toolbox users are already using it• Integrates with Docker Swarm

• It is not necessarily portable

php[tek] 2017 107

Let’s make a machine!

php[tek] 2017 108

Let’s Connect!

php[tek] 2017 109

php[tek] 2017

BREAK TIME AGAIN! WOO!

110

Production Considerations

php[tek] 2017 111

12 Factor Applications

php[tek] 2017 112

1. Codebase

One codebase tracked in revision control, many deploys

php[tek] 2017 113

Repo Tips

• Keep everything in your repository• Tag releases• Never move tags

php[tek] 2017 114

2. Dependencies

Explicitly declare and isolate dependencies

php[tek] 2017 115

Dependencies

• Commit both composer.json and composer.lock files• Commit Dockerfiles to the same repo as the codebase

php[tek] 2017 116

3. Config

Store config in the environment

php[tek] 2017 117

Configuration

• Anything that is environment specific should move to environment vars• Makes it much easier to build and deploy code• Code cares less what external services it is talking to

php[tek] 2017 118

Use Environment Vars

• Can specify them one-by-one– docker run ­e VAR_NAME=value

• Can specify a file– docker run ­­env­file=filename

• Can specify in docker-compose.yml

php[tek] 2017 119

4. Backing Services

Treat backing services as attached resources

php[tek] 2017 120

Everything is “external”

• Never talk to local sockets• Don’t make a determination between “locally” hosted and third party• Easier to switch environments• Easier to scale up

php[tek] 2017 121

5. Build, release, run

Strictly separate build and run stages

php[tek] 2017 122

The Workflow

• Build step installs dependencies, compiles files, and generates a Build Artifact that can be deployed

– Does not contain any deployment configuration

• Release step pushes a Build Artifact into an environment– Runs DB migrations, anything needed to happen before running

• Run step runs the app fully in the environment

php[tek] 2017 123

Tips

• Build Artifact can be an image• Builds should be completely reproducible• Release always take a build artifact, never directly from the repo• Tag all your builds• Track all your releases

php[tek] 2017 124

Build Step - Start Small

• Build your application• Run composer• Run npm/bower• Build JS/CSS

• Use the compiled output to build an image with docker build• Push full image to private registry

php[tek] 2017 125

docker build

• Additional options to look at• -f, --file – Specify a different filename for the Dockerfile• --no-cache – Don’t use a cached layer• --pull – Always pull a new version of the image

php[tek] 2017 126

Sample usage

docker build \

--no-cache \

–f docker/php/phpserver.dockerfile \

–t prod_php /opt/builds/20161010

php[tek] 2017 127

phpserver.dockerfile

FROM php:fpm

RUN docker-php-ext-install pdo pdo_mysql

COPY ./ /var/www

php[tek] 2017 128

6. Processes

Execute the app as one or more stateless processes

php[tek] 2017 129

Built Into Docker

• One Process per container• Allows tools to scale just what needs to be scaled• Allows images to be swapped out as needed

php[tek] 2017 130

7. Port Binding

Export services via port binding

php[tek] 2017 131

Built Into Docker (Again)

• Each container gets its own IP and exposes its own ports• Processes should already be talking over a network• Can work with service locators that are port-based

php[tek] 2017 132

8. Concurrency

Scale out via the process model

php[tek] 2017 133

How well does your app handle scaling?

php[tek] 2017 134

Built Into Docker (Again) (Again)

• One Process per container• Scale up just the container that is needed• App should not care how many instances of each service are running

php[tek] 2017 135

9. Disposability

Maximize robustness with fast startup and graceful shutdown

php[tek] 2017 136

Signals

• Docker starts containers fairly quickly• Applications should gracefully shut down, not just die• Docker sends a SIGTERM when shutting down a container• Your CLI apps may need to handle SIGTERM properly

– Cal Evans, “Signalling PHP”

php[tek] 2017 137

10. Dev/prod Parity

Keep development, staging, and production as similar as possible

php[tek] 2017 138

11. Logs

Treat logs as event streams

php[tek] 2017 139

Logging in Docker

• Various logging options built in– JSON file (default)– Fluentd– Syslog– Journald– Gelf– Splunk– Aws– Etwlogs– Gcplogs

php[tek] 2017 140

Push logs remotely

• When possible, push Docker logs to a remote service– Container logs only exist while the container exists

• Allows logs to be viewed in a single place• No need to get into actual servers• Can host yourself, or pay for a SaaS• ELK stack is very popular

– Docker uses fluentd instead

php[tek] 2017 141

Setting up fluentdservices:

  d4dapp:

    build: ./docker/d4dapp

    depends_on:

      ­ fluentd

    volumes:

      ­ ./:/var/www/

    ports:

      ­ 8080:80

    logging:

      driver: "fluentd"

      options:

        fluentd­address: 127.0.0.1:24224

        tag: apache.access

php[tek] 2017 142

Setting up fluentdservices:

  fluentd:

    build: docker/fluentd

    depends_on:

      ­ elasticsearch

    volumes:

      ­ ./docker/fluentd/fluent.conf:/fluentd/etc/fluent.conf

    ports:

      ­ 24224:24224

      ­ 24224:24224/udp

php[tek] 2017 143

Setting up fluentdFROM fluent/fluentd

RUN ["gem", "install", "fluent­plugin­elasticsearch", "­­no­rdoc", "­­no­ri", "­­version", "1.9.2"]

php[tek] 2017 144

Setting up fluentd[See Config File in repo]

php[tek] 2017 145

Setting up ElasticSearch and Kibanaservices:

  elasticsearch:

    image: elasticsearch

    expose:

      ­ 9200

    ports:

      ­ 9200:9200

  kibana:

    image: kibana

    depends_on:

      ­ elasticsearch

    ports:

      ­ 5601:5601

php[tek] 2017 146

Viewing Logs

php[tek] 2017 147

Logging notes

• docker logs does not work with external logging, only JSON• This example can be cleaned up a bit• Kibana syntax can be a bit odd to work with

php[tek] 2017 148

12. Admin Processes

Run admin/management tasks as one-off processes

php[tek] 2017 149

php[tek] 2017

BREAK TIME AGAIN! WOO!

150

Deployment using Docker Compose

php[tek] 2017 151

Very Good for Small Deployments

• Can be used to augment your dev environment• Works well with Docker Machine

php[tek] 2017 152

Create a machine

docker-machine create --driver digitalocean \

--digital-ocean-access-token [token] \

sunshinephp2017

php[tek] 2017 153

SunshinePHP 2017 154

Switch to the remote node

• Run docker-machine env sunshinephp2017

& "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env sunshinephp2017 | Invoke-Expression

php[tek] 2017 155

Set up docker-compose

• Docker Compose allows multiple config files with -f• Have a base docker-compose.yml for Production• Add a secondary one for Development

php[tek] 2017 156

version: '2'

volumes:

mysqldata:

driver: local

services:

nginx:

build:

context: ./

dockerfile: ./nginx.dockerfile

ports:

- 80:80

- 443:443

phpserver:

build:

context: ./

dockerfile: ./phpserver.dockerfile

working_dir: /var/www/public

mysqlserver:

image: mysql

environment:

[redacted]

volumes:

- mysqldata:/var/lib/mysql

php[tek] 2017 157

docker-compose.yml

version: '2'

volumes:

mysqldata:

driver: local

services:

nginx:

image: nginx

volumes:

- ./output_dev:/var/www/public:ro

- ./app/nginx/default.conf:/etc/nginx/conf.d/default.conf

- ./ssl:/etc/nginx/ssl/

phpserver:

build:

context: ./

dockerfile: ./phpserver.dockerfile

working_dir: /var/www/public

volumes:

- ./app:/var/www/

- ./vendor:/var/www/vendor

mysqlserver:

image: mysql

environment:

[redacted]

volumes:

- mysqldata:/var/lib/mysql

php[tek] 2017 158

docker-compose.dev.yml

When doing development

docker-compose \

–f docker-compose.yml \

–f docker-compose.dev.yml \

up -d

php[tek] 2017 159

When doing a deployment

docker-compose up -d

php[tek] 2017 160

Other Alternative – Variable Substitution

• Docker Compose allows variable substitution inside the file• Wrap variables in ${}• image: ${DEPLOY_VERSION}_php

php[tek] 2017 161

When doing a deployment

docker-compose up -d

php[tek] 2017 162

Docker Swarm

php[tek] 2017 163

What is Swarm?

• Docker-supplied clustering• Define a series of services that can be deployed

php[tek] 2017 164

Setup

php[tek] 2017 165

Manager

Node 2Node 1

Register a node as a Manager

docker swarm init ----advertise--addr 172.16.0.245

php[tek] 2017 166

Add nodes

docker swarm join --token [token] 172.16.0.245:2377

php[tek] 2017 167

docker-compose.yml

version: '3'

services:

phpserver:

image: php:apache

ports:

- 80:80

php[tek] 2017 168

Deploy the stack

$ docker stack deploy -c docker-compose.yml myapp

Creating network myapp_default

Creating service myapp_phpserver

php[tek] 2017 169

docker-compose.yml

version: '3'

services:

phpserver:

image: php:apache

ports:

- 80:80

php[tek] 2017 170

Deploy the stack

$ docker stack deploy -c docker-compose.yml myapp

Creating network myapp_default

Creating service myapp_phpserver

php[tek] 2017 171

docker-compose.yml

version: '3'

services:

phpserver:

image: php:apache

ports:

- 80:80

php[tek] 2017 172

docker-compose.yml

version: '3'

services:

phpserver:

image: php:apache

ports:

- 80:80

php[tek] 2017 173

docker stack ps myappID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS

72mud5othsjf myapp_phpserver.1 nginx:latest node2 Running Running 8 minutes ago

wsf3m32u9vcr \_ myapp_phpserver.1 php:apache manager1 Shutdown Shutdown 11 minutes ago

xf3wyh289bec myapp_phpserver.2 nginx:latest node1 Running Preparing 20 seconds ago

fehf1vdx4m0r myapp_phpserver.3 nginx:latest manager1 Running Preparing 20 seconds ago

pwnq65e6w7ew myapp_phpserver.4 nginx:latest manager1 Running Preparing 20 seconds ago

roxtanjughq8 myapp_phpserver.5 nginx:latest node2 Running Running 20 seconds ago

php[tek] 2017 174

php[tek] 2017

Thank You!

• Software Engineer for InQuest• Author of “Docker for Developers”• https://leanpub.com/dockerfordevs

• Co-Host of “Jerks Talk Games”• http://jerkstalkgames

• http://ctankersley.com• [email protected]• @dragonmantank

175