Zend Server in Docker Swarm:
Deployment and More

Jan Burkl
Solution Consulting Manager
Rogue Wave Software


ZendCon 2017, Las Vegas, October 26th 2017

Docker

Dockerfile (Prod)

FROM php:7.0-fpm

RUN apt-get update && apt-get install -y git libcurl4-gnutls-dev zlib1g-dev libicu-dev g++ libxml2-dev libpq-dev \
 && git clone -b php7 https://github.com/phpredis/phpredis.git /usr/src/php/ext/redis \
 && docker-php-ext-install redis \
 && apt-get autoremove && apt-get autoclean \
 && rm -rf /var/lib/apt/lists/*

#-------------------------------------------------------------------------------
# App sources
#-------------------------------------------------------------------------------
COPY . /app/
    

Dockerfile (Dev)

FROM janatzend/particulum-mobile-backend

WORKDIR /
ADD http://www.zend.com/en/download/4843?start=true /zend-debugger
RUN \
  echo zend_extension=/zend-debugger/ZendDebugger-linux-x86_64/php-7.0.x/ZendDebugger.so >> /usr/local/etc/php/php.ini && \
  echo zend_debugger.allow_from_all=1 >> /usr/local/etc/php/php.ini
    

Redis Container

$ docker run -d --name redis redis:3.2.7-alpine
    

PHP container

$ docker run -d --name php \
    -v "$PWD:/app" \
    --link redis:redis \
    particulummobile-dev/backend
    

Nginx Container

$ docker run -d --name nginx \
    -v "$PWD:/app" \
    -v "$PWD/etc/nginx.site.conf:/etc/nginx/conf.d/default.conf" \
    --link php:php \
    -p 8888:80 \
    particulummobile-dev/backend-nginx
    

Docker Compose

version: "3"

services:

#-------------------------------------------------------------------------------
# Nginx
#-------------------------------------------------------------------------------
  nginx:
    build:
      context: "${PROJECTS_PATH}/${BACKEND_APP_DIR}"
      dockerfile: Dockerfile.nginx
    image: particulummobile-dev/backend-nginx
    volumes:
      - "${PROJECTS_PATH}/${BACKEND_APP_DIR}/etc/nginx.site.conf:/etc/nginx/conf.d/default.conf"
      - "${PROJECTS_PATH}/${BACKEND_APP_DIR}:/app"
    networks:
      backend-net:

#-------------------------------------------------------------------------------
# php-fpm
#-------------------------------------------------------------------------------
  php:
    build:
      context: "${PROJECTS_PATH}/${BACKEND_APP_DIR}"
      dockerfile: Dockerfile.dev.vanilla-php
    image: particulummobile-dev/backend
    labels:
      com.roguewave.particulummobile.description: "Zend Expressive Backend for Particulum Mobile app"
      com.roguewave.particulummobile.service: "particulum-mobile-backend"
    volumes:
      - "${PROJECTS_PATH}/${BACKEND_APP_DIR}:/app"
    networks:
      backend-net:
        aliases:
          - backend-entry-point

#-------------------------------------------------------------------------------
# Redis
#-------------------------------------------------------------------------------
  redis:
    image: redis:3.2.7-alpine
    networks:
      backend-net:

networks:
  backend-net:
    

Run

$ docker-compose up
$ docker-compose -d -p $(PROJECT) -f $(DOCKER_COMPOSE_DEV_FILE) up

Scaling

$ docker-compose up -d --scale php=5
$ docker-compose scale php=5

Load Balancer?

Docker Swarm (Mode)

“Current versions of Docker include swarm mode for natively managing a cluster of Docker Engines called a swarm. Use the Docker CLI to create a swarm, deploy application services to a swarm, and manage swarm behavior.”

cloud.docker.com

  • Beta
  • Service Provider
    • AWS
    • Azure
    • On Premise

play-with-docker.com

Init / Manager

$ docker swarm init --advertise-addr 192.168.99.121
Swarm initialized: current node (ww4nime7fbh9twrzzl7o2t31f) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
      --token SWMTKN-1-2aps743f7wzjz6xp3vnlicpkim9ge2ykwvxkmkg7mep9ou0ie7-0vm4vc0e1q6ggj5auorm4vixd \
      192.168.33.101:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Networking

Routing Mesh

“The routing mesh enables each node in the swarm to accept connections on published ports for any service running in the swarm, even if there’s no task running on the node.”

Ingress Network

https://docs.docker.com/engine/swarm/ingress/

Services

Example:
Docker Swarm Visualizer

https://github.com/dockersamples/docker-swarm-visualizer

Create Service


  $ docker service create \
    --name=viz \
    --publish=8080:8080/tcp \
    --constraint=node.role==manager \
    --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
    dockersamples/visualizer

Building images

Makefile


    

App Services
Docker Compose v3


    

Install and Update


$ docker stack deploy --compose-file stack.yml pm
    

Zend Server

https://github.com/5square/docker-zendserver

Helpers

/run.sh

source /shell_functions.rc

trap "remove_from_cluster; exit" SIGINT SIGTERM SIGHUP
    

Web API

./etc/shell_functions.rc

WEB_API_KEY=docker
WEB_API_SECRET=$(cat /webapi/secret)

ZS_MANAGE=/usr/local/zend/bin/zs-manage
    

Config Import (Build time)

$ZS_CLIENT_A configurationImport \
  --configFile="/zs_config.zip" \
  --output-format="kv"
    

Joining Cluster

$ZS_MANAGE server-add-to-cluster \
  -n $HOSTNAME \
  -i $IP \
  -o $DB_HOST:3306 -u $DB_USER -p $DB_PASS -d $DB_NAME \
  -N $WEB_API_KEY -K $WEB_API_SECRET -s
    

Leaving Cluster

$ZS_MANAGE cluster-disable-server \
  $SERVER_ID -N $WEB_API_KEY -K $WEB_API_SECRET -s

$ZS_MANAGE cluster-remove-server \
  $SERVER_ID -N $WEB_API_KEY -K $WEB_API_SECRET -f
    

Session Clustering

Session Clustering

$ZS_MANAGE store-directive \
  -d 'session.save_handler' -v 'cluster' \
  -N $WEB_API_KEY -K $WEB_API_SECRET
    

Health Check

$ZS_CLIENT clusterGetServerStatus \
  --servers=$(cat /usr/local/zend/etc/conf.d/ZendGlobalDirectives.ini | grep zend.node_id | awk -F'=' '{print $2}') \
  --zsurl="http://localhost:10081" \
  --zskey=$WEB_API_KEY --zssecret=$WEB_API_SECRET \
  --output-format=kv \
  | grep status | grep OK || exit 1
    

    

Ingress Network - UI Issues

https://docs.docker.com/engine/swarm/ingress/

Updates

Zend Server Deployment?

Update

$ docker service update pm-zs_php --help

Usage:	docker service update [OPTIONS] SERVICE

Update a service

Options:
      --args command                       Service command args
      --config-add config                  Add or update a config file on a service
      --config-rm list                     Remove a configuration file
      --constraint-add list                Add or update a placement constraint
      --constraint-rm list                 Remove a constraint
      --container-label-add list           Add or update a container label
      --container-label-rm list            Remove a container label by its key
      --credential-spec credential-spec    Credential spec for managed service account (Windows only)
  -d, --detach                             Exit immediately instead of waiting for the service to converge (default true)
      --dns-add list                       Add or update a custom DNS server
      --dns-option-add list                Add or update a DNS option
      --dns-option-rm list                 Remove a DNS option
      --dns-rm list                        Remove a custom DNS server
      --dns-search-add list                Add or update a custom DNS search domain
      --dns-search-rm list                 Remove a DNS search domain
      --endpoint-mode string               Endpoint mode (vip or dnsrr)
      --entrypoint command                 Overwrite the default ENTRYPOINT of the image
      --env-add list                       Add or update an environment variable
      --env-rm list                        Remove an environment variable
      --force                              Force update even if no changes require it
      --group-add list                     Add an additional supplementary user group to the container
      --group-rm list                      Remove a previously added supplementary user group from the container
      --health-cmd string                  Command to run to check health
      --health-interval duration           Time between running the check (ms|s|m|h)
      --health-retries int                 Consecutive failures needed to report unhealthy
      --health-start-period duration       Start period for the container to initialize before counting retries towards
                                           unstable (ms|s|m|h)
      --health-timeout duration            Maximum time to allow one check to run (ms|s|m|h)
      --help                               Print usage
      --host-add list                      Add or update a custom host-to-IP mapping (host:ip)
      --host-rm list                       Remove a custom host-to-IP mapping (host:ip)
      --hostname string                    Container hostname
      --image string                       Service image tag
      --label-add list                     Add or update a service label
      --label-rm list                      Remove a label by its key
      --limit-cpu decimal                  Limit CPUs
      --limit-memory bytes                 Limit Memory
      --log-driver string                  Logging driver for service
      --log-opt list                       Logging driver options
      --mount-add mount                    Add or update a mount on a service
      --mount-rm list                      Remove a mount by its target path
      --network-add network                Add a network
      --network-rm list                    Remove a network
      --no-healthcheck                     Disable any container-specified HEALTHCHECK
      --no-resolve-image                   Do not query the registry to resolve image digest and supported platforms
      --placement-pref-add pref            Add a placement preference
      --placement-pref-rm pref             Remove a placement preference
      --publish-add port                   Add or update a published port
      --publish-rm port                    Remove a published port by its target port
  -q, --quiet                              Suppress progress output
      --read-only                          Mount the container's root filesystem as read only
      --replicas uint                      Number of tasks
      --reserve-cpu decimal                Reserve CPUs
      --reserve-memory bytes               Reserve Memory
      --restart-condition string           Restart when condition is met ("none"|"on-failure"|"any")
      --restart-delay duration             Delay between restart attempts (ns|us|ms|s|m|h)
      --restart-max-attempts uint          Maximum number of restarts before giving up
      --restart-window duration            Window used to evaluate the restart policy (ns|us|ms|s|m|h)
      --rollback                           Rollback to previous specification
      --rollback-delay duration            Delay between task rollbacks (ns|us|ms|s|m|h)
      --rollback-failure-action string     Action on rollback failure ("pause"|"continue")
      --rollback-max-failure-ratio float   Failure rate to tolerate during a rollback
      --rollback-monitor duration          Duration after each task rollback to monitor for failure (ns|us|ms|s|m|h)
      --rollback-order string              Rollback order ("start-first"|"stop-first")
      --rollback-parallelism uint          Maximum number of tasks rolled back simultaneously (0 to roll back all at once)
      --secret-add secret                  Add or update a secret on a service
      --secret-rm list                     Remove a secret
      --stop-grace-period duration         Time to wait before force killing a container (ns|us|ms|s|m|h)
      --stop-signal string                 Signal to stop the container
  -t, --tty                                Allocate a pseudo-TTY
      --update-delay duration              Delay between updates (ns|us|ms|s|m|h)
      --update-failure-action string       Action on update failure ("pause"|"continue"|"rollback")
      --update-max-failure-ratio float     Failure rate to tolerate during an update
      --update-monitor duration            Duration after each task update to monitor for failure (ns|us|ms|s|m|h)
      --update-order string                Update order ("start-first"|"stop-first")
      --update-parallelism uint            Maximum number of tasks updated simultaneously (0 to update all at once)
  -u, --user string                        Username or UID (format: [:])
      --with-registry-auth                 Send registry authentication details to swarm agents
  -w, --workdir string                     Working directory inside the container

Update

$ docker service update pm-zs_php \
  --image janatzend/particulum-mobile-backend-zendserver:update

or... UI
(Portainer)

Benefits

Containers self-contained

  • Everything in VCS
  • Running in every Docker env

Docker Compose

Stack Deployment via YAML file

DANKESCHÖN

bitbucket.org/account/user/5square-rw/projects/PM

Slides: 5square.de/talks

Contact me: jan.burkl [at] roguewave.com

Follow me: @5square_de