DOCKER
FOR DEVELOPMENT
…
https://joind.in/talk/51971
Toby Griffiths
@ToG
Cubic Mushroom Ltd.
Docker - From development to production
A BRIEF HISTORY OF ME
‣ PHP Developer since early 2000s
‣ Self-employed web developer since 2011
‣ Contracted for various companies
‣ Experienced problems of inconsistent development/
production environments
‣ Some server configuration knowledge
‣ Using Docker for 12+ months
‣ What is Docker?
‣ Docker for development
‣ Basic commands
‣ Running & linking multiple 

containers
‣ Customising images
‣ Gotchas
‣ Security considerations
WHAT I’LL COVER
SO, WHAT IS DOCKER?
Docker… it’s like virtual
machines, right?
Me, when I first discovered Docker
Docker - From development to production
Docker - From development to production
ADVANTAGES OF DOCKER OVER REGULAR VMS
▸ Smaller in size
▸ Don’t require a fully functional OS
▸ Can share read only file systems between containers
▸ Start up time
▸ Scalability
▸ Reduced resource requirements
▸ Can run 1000s of containers on a single host
▸ Reduced hardware requirements
WE ALREADY HAVE
SYSTEM THAT WORKS
WHY DOCKER?
Docker - From development to production
DOCKER FOR DEVELOPMENT
▸ Consistent environments
▸ (Almost) No more "works for me" problems
▸ Ease of setup*
▸ Easier upgrades
▸ Easier to develop and test distributed services
▸ Causes better designed architecture
* Unless you’re using Windows
Docker - From Development to Production
DOCKER FOR PRODUCTION
▸ Consistent environments
▸ (Almost) No more "works for me" problems
▸ Better resource management
▸ Scalability
▸ Faster spin-up times
It does solve a lot of
problems, if you are facing
them
@dennisdegreef
Docker - From development to production
RUNNING CONTAINERS
// List images
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest d20ae45477cb 10 days ago 1.13MB
Docker - From development to production
CONTAINER IMAGES
// Pulling images
$ docker pull busybox
// Remove an image
$ docker rmi busybox
// Pulling and running
// If image is not found locally it will be pulled from registry
$ docker run --rm busybox:1.27.2 echo "Hello world"
Docker - From development to production
RUNNING CONTAINERS
// Locally stored containers
$ docker run --name my-busybox busybox:latest echo "Hello world"
// Automatically removing containers when they stop
$ docker run --rm busybox:latest echo "Hello world"
// Include stopped containers
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
636b77baa5c3 busybox "echo 'Hello world'" 1 second ago Exited (0) 4 seconds ago stoic_edison
fe68dac5f99c busybox "echo 'Hello world'" 3 seconds ago Exited (0) 5 seconds ago lucid_newton
171131c6a82d busybox "echo 'Hello world'" 4 seconds ago Exited (0) 8 seconds ago admiring_mirzakhani
8cbfcf2b2f32 nginx:latest "nginx -g 'daemon ..." 19 hours ago Up 19 hours 0.0.0.0:80->80/tcp, 443/tcp dockertalk_nginx_1
587849ab38e9 dockertalk_php "docker-php-entryp..." 19 hours ago Up 19 hours 9000/tcp dockertalk_php_1
1a8dbfc874a6 mysql:5.7 "docker-entrypoint..." 19 hours ago Up 19 hours 3306/tcp dockertalk_mysql_1
Docker - From development to production
VIEWING CONTAINERS
// Running containers
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8cbfcf2b2f32 nginx:latest "nginx -g 'daemon ..." 19 hours ago Up 19 hours 0.0.0.0:80->80/tcp, 443/tcp dockertalk_nginx_1
587849ab38e9 dockertalk_php "docker-php-entryp..." 19 hours ago Up 19 hours 9000/tcp dockertalk_php_1
1a8dbfc874a6 mysql:5.7 "docker-entrypoint..." 19 hours ago Up 19 hours 3306/tcp dockertalk_mysql_1
Docker - From development to production
CONTAINERS THAT WON'T QUIT
// Run continuous containers
$ docker run --name my-nginx nginx:latest
Docker - From development to production
CONTAINERS THAT WON'T QUIT
// Run continuous containers in the background
$ docker run --name my-nginx -d nginx:latest
$ docker ps --format 
"table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}"
Docker - From development to production
RUNNING SHELLS INSIDE CONTAINERS
// Interactive shell
$ docker run --rm -it --name my-busybox-shell
busybox:latest sh
Docker flags used here…
-t : Allocate a pseudo-tty
-i : Keep STDIN open even if not attached
// Run continuous container in the background
$ docker run --rm --name my-nginx -d nginx:latest
$ docker ps
Docker - From development to production
STOPPING AND REMOVING CONTAINERS
Docker - From development to production
STOPPING AND REMOVING CONTAINERS
// Stop a container
$ docker stop my-nginx
Docker - From development to production
STOPPING AND REMOVING CONTAINERS
// Run continuous container in the background
$ docker run --name my-nginx -d nginx:latest
$ docker ps
// Kill a container
$ docker kill my-nginx
// Removed stopped container
$ docker ps -a
$ docker rm my-nginx
$ docker ps -a
Docker - From development to production
STOPPING AND REMOVING CONTAINERS
PIMP MY CONTAINER
FROM php:7.1-cl
VOLUME /var/www/html
# … or, using JSON notation, (so use double, not single quotes)…
VOLUME ["/var/www/html", "/var/log"]
WORKDIR /var/www/html
# Add content of files to /var/www/html
ADD ./files /var/www/html
# Add content of files to /var/www/html/files
ADD ./files /var/www/html/
# Add a remote download file
ADD http://example.com/foobar /var/www/html
# Add and decompress a LOCAL archive file
ADD ./files/archive.tar.gz /var/www/html
# Copy file without decompressing
COPY ./files/archive.tar.gz /var/www/html
Docker - From development to production
CONFIGURE USING DOCKERFILES
FROM php:7.1-cl
# ...
ARG DEPLOY_STAGE
ARG DEPLOY_ENV=test
ENV SYMFONY_ENV=dev
EXPOSE 9000
USER www-data
GROUP www-data
ONBUILD RUN composer install
LABEL multi.label1="value1"
Docker - From development to production
CONFIGURE USING DOCKERFILES
// Pass in build arguments to Dockerfile in the current
// directory
$ docker build 
--build-arg MYSQL_ROOT_PASSWORD=my-secret-pw 
.
Docker - From development to production
CONFIGURE DURING BUILD USING BUILD ARGUMENTS
// Pass in environment variables
$ docker run --rm --name my-mysql 
-e MYSQL_ROOT_PASSWORD=my-secret-pw 
-d mysql:5.7
Docker - From development to production
CONFIGURE AT RUNTIME USING ENVIRONMENT VARIABLES
// Pass in environment variables
$ docker run --rm --name my-mysql 
--env-file /my/dirty/secrets 
-d mysql:5.7
WHERE ARE MY FILES?
Docker - From development to production
USING VOLUMES
// Mapping volumes
$ docker run --rm busybox:latest ls -als /usr
$ docker run --rm -v "$PWD/files:/usr/files" busybox:latest ls -als /usr
$ docker run --rm -v "$PWD/files:/usr/files" busybox:latest ls -als /usr/files
Docker - From development to production
USING VOLUMES - OVERWRITING DIRECTORIES
// Overwriting directories
$ docker run --rm busybox:latest ls -als /usr
$ docker run --rm -v "$PWD/files:/usr" busybox:latest ls -als /usr
Docker - From development to production
USING VOLUMES - NAMED VOLUMES
// Named volumes
$ docker run --rm busybox:latest ls -als /usr
$ docker run --rm -v named_volume:/usr busybox:latest ls -als /usr
$ docker run --rm -v named_volume:/named busybox:latest ls -als /named
INSPECT ALL THE THINGS
// Inspect images
$ docker inspect busybox:latest | jq
Docker - From development to production
INSPECTING IMAGES, CONTAINERS AND MORE
Docker - From development to production
VIEWING CONTAINER LOGS
// View logs
$ docker logs my-mysql
// Follow logs
$ docker logs -f my-mysql
TYING THINGS TOGETHER
Docker - From development to production
LINKING CONTAINERS
$ docker run --rm --name my-nginx -d nginx:latest
$ docker ps --format "table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}"
$ docker run --rm busybox ping my-nginx
Docker - From development to production
LINKING CONTAINERS
$ docker network create phpnw
$ docker inspect -f "{{json .Containers}}" phpnw | jq
$ docker network connect phpnw my-nginx
$ docker inspect -f "{{json .Containers}}" phpnw | jq
Docker - From development to production
LINKING CONTAINERS
// Ping container from another
$ docker run --rm --network phpnw busybox 
ping -c 4 my-nginx
DON’T STOP!
// Demo sleep container
$ docker run --rm --name dont-restart-me -d busybox sleep 3
$ docker ps -a --format "table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}"
// Always restart container
$ docker run --name restart-me -d --restart=always busybox sleep 3
$ docker ps -a --format "table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}"
Docker - From development to production
KEEPING CONTAINERS RUNNING
Docker - From development to production
KEEPING CONTAINERS RUNNING - INSPECTING DETAILS
// Viewing the restart count
$ docker inspect -f "{{ .RestartCount }}" restart-me
$ docker inspect -f "{{ .State.StartedAt }}" restart-me
// Stop & remove container
$ docker stop restart-me
$ docker rm restart-me
$ docker ps -a --format "table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}"
Docker - From development to production
RESTART OPTIONS
Restart options…
no : (Default) Do not restart container when it
exits.
on-failure[:max-retries] : Restart only if the container
exits with a non-zero exit status.
Optionally, limit the number of restart
retries the Docker daemon attempts.
always : Always restart the container regardless of
the exit status.
Daemon will try to restart the container
indefinitely.
Will also always start on daemon startup.
unless-stopped : Always restart the container regardless of
the exit status, but do not start it on
daemon startup if the container has been
put to a stopped state before.
LET ME IN
Docker - From development to production
ACCESSING CONTAINERS FROM THE OUTSIDE WORLD
// Launch container
$ docker run --rm --name my-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7
$ docker ps --format "table {{.ID}}t{{.Image}}t{{.Status}}t{{.Ports}}"
$ docker stop my-mysql
Docker - From development to production
ACCESSING CONTAINERS FROM THE OUTSIDE WORLD
$ docker run --rm --name my-mysql --env-file /my/dirty/secrets -d -P mysql:5.7
$ docker ps --format "table {{.ID}}t{{.Image}}t{{.Status}}t{{.Ports}}"
$ docker run --rm --name my-mysql2 --env-file /my/dirty/secrets -d -p 80:80 mysql:5.7
$ docker ps --format "table {{.ID}}t{{.Image}}t{{.Status}}t{{.Ports}}"
Docker - From development to production
NETWORK OPTIONS
The following flags are available for controlling network settings for containers…
--dns=[] : Set custom DNS servers for the container
--network="bridge" : Connect a container to a network
Options
- 'bridge' : create a network stack on the default Docker
bridge
- 'none' : no networking
- 'container:<name|id>' : reuse another container's network
stack
- 'host' : use the Docker host network stack
- '<network-name>|<network-id>': connect to a user-defined
network
--network-alias=[] : Add network-scoped alias for the container
--add-host="" : Add a line to /etc/hosts (host:IP)
--mac-address="" : Sets the container's Ethernet device's MAC address
--ip="" : Sets the container's Ethernet device's IPv4 address
--ip6="" : Sets the container's Ethernet device's IPv6 address
--link-local-ip=[] : Sets one or more container's Ethernet device's
link local IPv4/IPv6 addresses
Docker - From development to production
RESOURCES OPTIONS
The following flags are available for controlling resource usage…
-m, --memory="" : Memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be
one of
b, k, m, or g. Minimum is 4M.
--memory-swap="" : Total memory limit (memory + swap, format: <number>[<unit>]). Number is a positive
integer. Unit can be one of b, k, m, or g.
--memory-reservation="" : Memory soft limit (format: <number>[<unit>]). Number is a positive integer. Unit can
be
one of b, k, m, or g.
--kernel-memory="" : Kernel memory limit (format: <number>[<unit>]). Number is a positive integer. Unit
can be
one of b, k, m, or g. Minimum is 4M.
-c, --cpu-shares=0 : CPU shares (relative weight)
--cpus=0.000 : Number of CPUs. Number is a fractional number. 0.000 means no limit.
--cpu-period=0 : Limit the CPU CFS (Completely Fair Scheduler) period
--cpuset-cpus="" : CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems="" : Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA
systems.
--cpu-quota=0 : Limit the CPU CFS (Completely Fair Scheduler) quota
--cpu-rt-period=0 : Limit the CPU real-time period. In microseconds. Requires parent cgroups be set and
cannot be higher than parent. Also check rtprio ulimits.
--cpu-rt-runtime=0 : Limit the CPU real-time runtime. In microseconds. Requires parent cgroups be set and
cannot be higher than parent. Also check rtprio ulimits.
--blkio-weight=0 : Block IO weight (relative weight) accepts a weight value between 10 and 1000.
… [and more options]
EXAMPLES
HELLO WORLD
(AND A LITTLE GOLANG FOR YOU)
Docker - From development to production
HELLO WORLD
// hello-world.go
package main
import "fmt"
func main() {
fmt.Printf(
"Hello, PHP North Westn”
)
}
$ docker run --rm 
-v "$PWD/files":/go 
golang go run hello-world.go
Docker - From development to production
HELLO WORLD
// hello-world.go
package main
import "fmt"
func main() {
fmt.Printf(
"Hello, PHP North Westn”
)
}
$ docker run --rm 
-v "$PWD/files":/go 
-e GOOS=darwin 
golang go build hello-world.go
$ ./files/hello-world
(L)EMP
Docker - From development to production
AN NGINX WEB SERVER
// Expose container ports on defined host ports
$ docker run --rm --name my-nginx -d -p 80:80 nginx
$ docker ps
Docker - From development to production
AN NGINX WEB SERVER - WITH FILES
// Expose container ports on defined
// host ports
$ docker run --rm --name my-nginx 
-v "$PWD/files":/usr/share/nginx/html:ro 
-p 80:80 
-d
nginx
$ docker ps
<!-- ./files/index.html -->
<!doctype html>
<html lang="en">
<head>
<title>Hello, PHP North West!</title>
</head>
<body>
<h1>Hello, PHP North West!</h1>
</body>
</html>
DOCKER COMPOSE
Docker - From development to production
DOCKER COMPOSE
version: '3'
services:
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: phpnw
volumes:
- mysql_data:/var/lib/mysql:delegated
restart: unless-stopped
php:
build: ./files/docker/php/docker
volumes:
- web_files:/usr/share/nginx/html
depends_on:
- mysql
restart: unless-stopped
Docker - From development to production
DOCKER COMPOSE - VOLUMES
version: '3'
services:
# ...
nginx:
image: nginx:latest
volumes:
- ./files/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:delegated
- ./files/docker/nginx/conf/conf.d/upstream.conf:/etc/nginx/conf.d/upstream.conf:delegated
- ./files/docker/nginx/conf/conf.d/default.dev.conf:/etc/nginx/conf.d/default.conf:delegated
- web_files:/usr/share/nginx/html
ports:
- 80:80
depends_on:
- php
restart: unless-stopped
volumes:
mysql_data: ~
# named volume mapped to host directory
web_files:
driver: local-persist # <<== uses local-persist plugin
driver_opts:
mountpoint: /path/on/host/machine/
Docker - From development to production
DOCKER COMPOSE
$ docker-compose up
Docker - From development to production
DOCKER COMPOSE
$ docker-compose up -d
Docker - From development to production
DOCKER COMPOSE - LOGS
$ docker-compose logs -f
IMAGE SIZE
FROM php:7.1-apache
RUN apt-get update && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev 
libmcrypt-dev libpng12-dev
RUN docker-php-ext-install -j$(nproc) iconv mcrypt
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/
--with-jpeg-dir=/usr/include/
RUN docker-php-ext-install -j$(nproc) gd
RUN docker-php-source delete
FROM php:7.1-apache
RUN apt-get update && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev 
libmcrypt-dev libpng12-dev 
&& docker-php-ext-install -j$(nproc) iconv mcrypt 
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ 
--with-jpeg-dir=/usr/include/ 
&& docker-php-ext-install -j$(nproc) gd 
&& docker-php-source delete
Docker - From development to production
DOCKERFILES - A NOTE ABOUT IMAGE SIZES
VS
FROM php:7.1-apache
RUN apt-get update && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev 
libmcrypt-dev libpng12-dev
RUN docker-php-ext-install -j$(nproc) iconv mcrypt
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/
--with-jpeg-dir=/usr/include/
RUN docker-php-ext-install -j$(nproc) gd
RUN docker-php-source delete
Docker - From development to production
DOCKERFILES - A NOTE ABOUT IMAGE SIZES
5 x RUN commands = 5 x image layers
FROM php:7.1-apache
RUN apt-get update && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev 
libmcrypt-dev libpng12-dev 
&& docker-php-ext-install -j$(nproc) iconv mcrypt 
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ 
--with-jpeg-dir=/usr/include/ 
&& docker-php-ext-install -j$(nproc) gd 
&& docker-php-source delete
Docker - From development to production
DOCKERFILES - A NOTE ABOUT IMAGE SIZES
1 x RUN commands = 1 x image layers
FILESYSTEM LIMITATIONS
Docker - From development to production
FILESYSTEM LIMITATIONS
‣ File name length limit
‣ Limit of 242 characters (rather than 255)
‣ Symfony/Doctrine cache files
‣ Prepare cache inside the container
Docker - From development to production
FILESYSTEM LIMITATIONS
‣ Docker for Mac
‣ Performance issues
‣ Use :cached or :delegated suffix on volume
declarations, to allow delayed updates…



$ docker run -v "$PWD:/home:cached" php:7.1-cli

$ docker run -v "$PWD:/home:delegated" php:7.1-cli
Docker - From development to production
FILESYSTEM LIMITATIONS
‣ File permissions on volumes differ between hosts types
‣ On Docker for Mac the permissions are kept to those of
the running user
‣ On Docker for Linux the permissions on the host match
the user:group IDs set within the container
‣ Window???
SECURITY
Docker - From development to production
SECURITY CONSIDERATIONS
‣ Kernel exploits
‣ Kernel panics within container will bring down the host machine
‣ Denial of Service
‣ Containers can hog host resources
‣ Image trustworthiness
‣ Secrets
‣ Confidential information can be stored into Docker images (e.g. in
--build-args), if not careful
Docker - From development to production
SECURITY CONSIDERATIONS
‣ Patching core packages
‣ Run system updates within container?
‣ Update packages on image build, and re-build regularly
‣ Container breakout
‣ User permissions in the container = user permissions
outside
‣ Namespace users (see http://dockr.ly/2wEfy2g)
The End!
Toby Griffiths
@ToG
Cubic Mushroom Ltd.
https://joind.in/talk/51971

Docker - from development to production (PHPNW 2017-09-05)

  • 1.
  • 2.
  • 3.
    Docker - Fromdevelopment to production A BRIEF HISTORY OF ME ‣ PHP Developer since early 2000s ‣ Self-employed web developer since 2011 ‣ Contracted for various companies ‣ Experienced problems of inconsistent development/ production environments ‣ Some server configuration knowledge ‣ Using Docker for 12+ months
  • 4.
    ‣ What isDocker? ‣ Docker for development ‣ Basic commands ‣ Running & linking multiple 
 containers ‣ Customising images ‣ Gotchas ‣ Security considerations WHAT I’LL COVER
  • 5.
    SO, WHAT ISDOCKER?
  • 6.
    Docker… it’s likevirtual machines, right? Me, when I first discovered Docker Docker - From development to production
  • 7.
    Docker - Fromdevelopment to production ADVANTAGES OF DOCKER OVER REGULAR VMS ▸ Smaller in size ▸ Don’t require a fully functional OS ▸ Can share read only file systems between containers ▸ Start up time ▸ Scalability ▸ Reduced resource requirements ▸ Can run 1000s of containers on a single host ▸ Reduced hardware requirements
  • 8.
    WE ALREADY HAVE SYSTEMTHAT WORKS WHY DOCKER?
  • 9.
    Docker - Fromdevelopment to production DOCKER FOR DEVELOPMENT ▸ Consistent environments ▸ (Almost) No more "works for me" problems ▸ Ease of setup* ▸ Easier upgrades ▸ Easier to develop and test distributed services ▸ Causes better designed architecture * Unless you’re using Windows
  • 10.
    Docker - FromDevelopment to Production DOCKER FOR PRODUCTION ▸ Consistent environments ▸ (Almost) No more "works for me" problems ▸ Better resource management ▸ Scalability ▸ Faster spin-up times
  • 11.
    It does solvea lot of problems, if you are facing them @dennisdegreef Docker - From development to production
  • 12.
  • 13.
    // List images $docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest d20ae45477cb 10 days ago 1.13MB Docker - From development to production CONTAINER IMAGES // Pulling images $ docker pull busybox // Remove an image $ docker rmi busybox
  • 14.
    // Pulling andrunning // If image is not found locally it will be pulled from registry $ docker run --rm busybox:1.27.2 echo "Hello world" Docker - From development to production RUNNING CONTAINERS // Locally stored containers $ docker run --name my-busybox busybox:latest echo "Hello world" // Automatically removing containers when they stop $ docker run --rm busybox:latest echo "Hello world"
  • 15.
    // Include stoppedcontainers $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 636b77baa5c3 busybox "echo 'Hello world'" 1 second ago Exited (0) 4 seconds ago stoic_edison fe68dac5f99c busybox "echo 'Hello world'" 3 seconds ago Exited (0) 5 seconds ago lucid_newton 171131c6a82d busybox "echo 'Hello world'" 4 seconds ago Exited (0) 8 seconds ago admiring_mirzakhani 8cbfcf2b2f32 nginx:latest "nginx -g 'daemon ..." 19 hours ago Up 19 hours 0.0.0.0:80->80/tcp, 443/tcp dockertalk_nginx_1 587849ab38e9 dockertalk_php "docker-php-entryp..." 19 hours ago Up 19 hours 9000/tcp dockertalk_php_1 1a8dbfc874a6 mysql:5.7 "docker-entrypoint..." 19 hours ago Up 19 hours 3306/tcp dockertalk_mysql_1 Docker - From development to production VIEWING CONTAINERS // Running containers $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8cbfcf2b2f32 nginx:latest "nginx -g 'daemon ..." 19 hours ago Up 19 hours 0.0.0.0:80->80/tcp, 443/tcp dockertalk_nginx_1 587849ab38e9 dockertalk_php "docker-php-entryp..." 19 hours ago Up 19 hours 9000/tcp dockertalk_php_1 1a8dbfc874a6 mysql:5.7 "docker-entrypoint..." 19 hours ago Up 19 hours 3306/tcp dockertalk_mysql_1
  • 16.
    Docker - Fromdevelopment to production CONTAINERS THAT WON'T QUIT // Run continuous containers $ docker run --name my-nginx nginx:latest
  • 17.
    Docker - Fromdevelopment to production CONTAINERS THAT WON'T QUIT // Run continuous containers in the background $ docker run --name my-nginx -d nginx:latest $ docker ps --format "table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}"
  • 18.
    Docker - Fromdevelopment to production RUNNING SHELLS INSIDE CONTAINERS // Interactive shell $ docker run --rm -it --name my-busybox-shell busybox:latest sh Docker flags used here… -t : Allocate a pseudo-tty -i : Keep STDIN open even if not attached
  • 19.
    // Run continuouscontainer in the background $ docker run --rm --name my-nginx -d nginx:latest $ docker ps Docker - From development to production STOPPING AND REMOVING CONTAINERS
  • 20.
    Docker - Fromdevelopment to production STOPPING AND REMOVING CONTAINERS // Stop a container $ docker stop my-nginx
  • 21.
    Docker - Fromdevelopment to production STOPPING AND REMOVING CONTAINERS // Run continuous container in the background $ docker run --name my-nginx -d nginx:latest $ docker ps // Kill a container $ docker kill my-nginx
  • 22.
    // Removed stoppedcontainer $ docker ps -a $ docker rm my-nginx $ docker ps -a Docker - From development to production STOPPING AND REMOVING CONTAINERS
  • 23.
  • 24.
    FROM php:7.1-cl VOLUME /var/www/html #… or, using JSON notation, (so use double, not single quotes)… VOLUME ["/var/www/html", "/var/log"] WORKDIR /var/www/html # Add content of files to /var/www/html ADD ./files /var/www/html # Add content of files to /var/www/html/files ADD ./files /var/www/html/ # Add a remote download file ADD http://example.com/foobar /var/www/html # Add and decompress a LOCAL archive file ADD ./files/archive.tar.gz /var/www/html # Copy file without decompressing COPY ./files/archive.tar.gz /var/www/html Docker - From development to production CONFIGURE USING DOCKERFILES
  • 25.
    FROM php:7.1-cl # ... ARGDEPLOY_STAGE ARG DEPLOY_ENV=test ENV SYMFONY_ENV=dev EXPOSE 9000 USER www-data GROUP www-data ONBUILD RUN composer install LABEL multi.label1="value1" Docker - From development to production CONFIGURE USING DOCKERFILES
  • 26.
    // Pass inbuild arguments to Dockerfile in the current // directory $ docker build --build-arg MYSQL_ROOT_PASSWORD=my-secret-pw . Docker - From development to production CONFIGURE DURING BUILD USING BUILD ARGUMENTS
  • 27.
    // Pass inenvironment variables $ docker run --rm --name my-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7 Docker - From development to production CONFIGURE AT RUNTIME USING ENVIRONMENT VARIABLES // Pass in environment variables $ docker run --rm --name my-mysql --env-file /my/dirty/secrets -d mysql:5.7
  • 28.
  • 29.
    Docker - Fromdevelopment to production USING VOLUMES // Mapping volumes $ docker run --rm busybox:latest ls -als /usr $ docker run --rm -v "$PWD/files:/usr/files" busybox:latest ls -als /usr $ docker run --rm -v "$PWD/files:/usr/files" busybox:latest ls -als /usr/files
  • 30.
    Docker - Fromdevelopment to production USING VOLUMES - OVERWRITING DIRECTORIES // Overwriting directories $ docker run --rm busybox:latest ls -als /usr $ docker run --rm -v "$PWD/files:/usr" busybox:latest ls -als /usr
  • 31.
    Docker - Fromdevelopment to production USING VOLUMES - NAMED VOLUMES // Named volumes $ docker run --rm busybox:latest ls -als /usr $ docker run --rm -v named_volume:/usr busybox:latest ls -als /usr $ docker run --rm -v named_volume:/named busybox:latest ls -als /named
  • 32.
  • 33.
    // Inspect images $docker inspect busybox:latest | jq Docker - From development to production INSPECTING IMAGES, CONTAINERS AND MORE
  • 34.
    Docker - Fromdevelopment to production VIEWING CONTAINER LOGS // View logs $ docker logs my-mysql // Follow logs $ docker logs -f my-mysql
  • 35.
  • 36.
    Docker - Fromdevelopment to production LINKING CONTAINERS $ docker run --rm --name my-nginx -d nginx:latest $ docker ps --format "table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}" $ docker run --rm busybox ping my-nginx
  • 37.
    Docker - Fromdevelopment to production LINKING CONTAINERS $ docker network create phpnw $ docker inspect -f "{{json .Containers}}" phpnw | jq $ docker network connect phpnw my-nginx $ docker inspect -f "{{json .Containers}}" phpnw | jq
  • 38.
    Docker - Fromdevelopment to production LINKING CONTAINERS // Ping container from another $ docker run --rm --network phpnw busybox ping -c 4 my-nginx
  • 39.
  • 40.
    // Demo sleepcontainer $ docker run --rm --name dont-restart-me -d busybox sleep 3 $ docker ps -a --format "table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}" // Always restart container $ docker run --name restart-me -d --restart=always busybox sleep 3 $ docker ps -a --format "table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}" Docker - From development to production KEEPING CONTAINERS RUNNING
  • 41.
    Docker - Fromdevelopment to production KEEPING CONTAINERS RUNNING - INSPECTING DETAILS // Viewing the restart count $ docker inspect -f "{{ .RestartCount }}" restart-me $ docker inspect -f "{{ .State.StartedAt }}" restart-me // Stop & remove container $ docker stop restart-me $ docker rm restart-me $ docker ps -a --format "table {{.ID}}t{{.Image}}t{{.Names}}t{{.Status}}"
  • 42.
    Docker - Fromdevelopment to production RESTART OPTIONS Restart options… no : (Default) Do not restart container when it exits. on-failure[:max-retries] : Restart only if the container exits with a non-zero exit status. Optionally, limit the number of restart retries the Docker daemon attempts. always : Always restart the container regardless of the exit status. Daemon will try to restart the container indefinitely. Will also always start on daemon startup. unless-stopped : Always restart the container regardless of the exit status, but do not start it on daemon startup if the container has been put to a stopped state before.
  • 43.
  • 44.
    Docker - Fromdevelopment to production ACCESSING CONTAINERS FROM THE OUTSIDE WORLD // Launch container $ docker run --rm --name my-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7 $ docker ps --format "table {{.ID}}t{{.Image}}t{{.Status}}t{{.Ports}}" $ docker stop my-mysql
  • 45.
    Docker - Fromdevelopment to production ACCESSING CONTAINERS FROM THE OUTSIDE WORLD $ docker run --rm --name my-mysql --env-file /my/dirty/secrets -d -P mysql:5.7 $ docker ps --format "table {{.ID}}t{{.Image}}t{{.Status}}t{{.Ports}}" $ docker run --rm --name my-mysql2 --env-file /my/dirty/secrets -d -p 80:80 mysql:5.7 $ docker ps --format "table {{.ID}}t{{.Image}}t{{.Status}}t{{.Ports}}"
  • 46.
    Docker - Fromdevelopment to production NETWORK OPTIONS The following flags are available for controlling network settings for containers… --dns=[] : Set custom DNS servers for the container --network="bridge" : Connect a container to a network Options - 'bridge' : create a network stack on the default Docker bridge - 'none' : no networking - 'container:<name|id>' : reuse another container's network stack - 'host' : use the Docker host network stack - '<network-name>|<network-id>': connect to a user-defined network --network-alias=[] : Add network-scoped alias for the container --add-host="" : Add a line to /etc/hosts (host:IP) --mac-address="" : Sets the container's Ethernet device's MAC address --ip="" : Sets the container's Ethernet device's IPv4 address --ip6="" : Sets the container's Ethernet device's IPv6 address --link-local-ip=[] : Sets one or more container's Ethernet device's link local IPv4/IPv6 addresses
  • 47.
    Docker - Fromdevelopment to production RESOURCES OPTIONS The following flags are available for controlling resource usage… -m, --memory="" : Memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M. --memory-swap="" : Total memory limit (memory + swap, format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g. --memory-reservation="" : Memory soft limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g. --kernel-memory="" : Kernel memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M. -c, --cpu-shares=0 : CPU shares (relative weight) --cpus=0.000 : Number of CPUs. Number is a fractional number. 0.000 means no limit. --cpu-period=0 : Limit the CPU CFS (Completely Fair Scheduler) period --cpuset-cpus="" : CPUs in which to allow execution (0-3, 0,1) --cpuset-mems="" : Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems. --cpu-quota=0 : Limit the CPU CFS (Completely Fair Scheduler) quota --cpu-rt-period=0 : Limit the CPU real-time period. In microseconds. Requires parent cgroups be set and cannot be higher than parent. Also check rtprio ulimits. --cpu-rt-runtime=0 : Limit the CPU real-time runtime. In microseconds. Requires parent cgroups be set and cannot be higher than parent. Also check rtprio ulimits. --blkio-weight=0 : Block IO weight (relative weight) accepts a weight value between 10 and 1000. … [and more options]
  • 48.
  • 49.
    HELLO WORLD (AND ALITTLE GOLANG FOR YOU)
  • 50.
    Docker - Fromdevelopment to production HELLO WORLD // hello-world.go package main import "fmt" func main() { fmt.Printf( "Hello, PHP North Westn” ) } $ docker run --rm -v "$PWD/files":/go golang go run hello-world.go
  • 51.
    Docker - Fromdevelopment to production HELLO WORLD // hello-world.go package main import "fmt" func main() { fmt.Printf( "Hello, PHP North Westn” ) } $ docker run --rm -v "$PWD/files":/go -e GOOS=darwin golang go build hello-world.go $ ./files/hello-world
  • 52.
  • 53.
    Docker - Fromdevelopment to production AN NGINX WEB SERVER // Expose container ports on defined host ports $ docker run --rm --name my-nginx -d -p 80:80 nginx $ docker ps
  • 54.
    Docker - Fromdevelopment to production AN NGINX WEB SERVER - WITH FILES // Expose container ports on defined // host ports $ docker run --rm --name my-nginx -v "$PWD/files":/usr/share/nginx/html:ro -p 80:80 -d nginx $ docker ps <!-- ./files/index.html --> <!doctype html> <html lang="en"> <head> <title>Hello, PHP North West!</title> </head> <body> <h1>Hello, PHP North West!</h1> </body> </html>
  • 55.
  • 56.
    Docker - Fromdevelopment to production DOCKER COMPOSE version: '3' services: mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: phpnw volumes: - mysql_data:/var/lib/mysql:delegated restart: unless-stopped php: build: ./files/docker/php/docker volumes: - web_files:/usr/share/nginx/html depends_on: - mysql restart: unless-stopped
  • 57.
    Docker - Fromdevelopment to production DOCKER COMPOSE - VOLUMES version: '3' services: # ... nginx: image: nginx:latest volumes: - ./files/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:delegated - ./files/docker/nginx/conf/conf.d/upstream.conf:/etc/nginx/conf.d/upstream.conf:delegated - ./files/docker/nginx/conf/conf.d/default.dev.conf:/etc/nginx/conf.d/default.conf:delegated - web_files:/usr/share/nginx/html ports: - 80:80 depends_on: - php restart: unless-stopped volumes: mysql_data: ~ # named volume mapped to host directory web_files: driver: local-persist # <<== uses local-persist plugin driver_opts: mountpoint: /path/on/host/machine/
  • 58.
    Docker - Fromdevelopment to production DOCKER COMPOSE $ docker-compose up
  • 59.
    Docker - Fromdevelopment to production DOCKER COMPOSE $ docker-compose up -d
  • 60.
    Docker - Fromdevelopment to production DOCKER COMPOSE - LOGS $ docker-compose logs -f
  • 61.
  • 62.
    FROM php:7.1-apache RUN apt-getupdate && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libpng12-dev RUN docker-php-ext-install -j$(nproc) iconv mcrypt RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ RUN docker-php-ext-install -j$(nproc) gd RUN docker-php-source delete FROM php:7.1-apache RUN apt-get update && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libpng12-dev && docker-php-ext-install -j$(nproc) iconv mcrypt && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && docker-php-ext-install -j$(nproc) gd && docker-php-source delete Docker - From development to production DOCKERFILES - A NOTE ABOUT IMAGE SIZES VS
  • 63.
    FROM php:7.1-apache RUN apt-getupdate && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libpng12-dev RUN docker-php-ext-install -j$(nproc) iconv mcrypt RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ RUN docker-php-ext-install -j$(nproc) gd RUN docker-php-source delete Docker - From development to production DOCKERFILES - A NOTE ABOUT IMAGE SIZES 5 x RUN commands = 5 x image layers
  • 64.
    FROM php:7.1-apache RUN apt-getupdate && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libpng12-dev && docker-php-ext-install -j$(nproc) iconv mcrypt && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && docker-php-ext-install -j$(nproc) gd && docker-php-source delete Docker - From development to production DOCKERFILES - A NOTE ABOUT IMAGE SIZES 1 x RUN commands = 1 x image layers
  • 65.
  • 66.
    Docker - Fromdevelopment to production FILESYSTEM LIMITATIONS ‣ File name length limit ‣ Limit of 242 characters (rather than 255) ‣ Symfony/Doctrine cache files ‣ Prepare cache inside the container
  • 67.
    Docker - Fromdevelopment to production FILESYSTEM LIMITATIONS ‣ Docker for Mac ‣ Performance issues ‣ Use :cached or :delegated suffix on volume declarations, to allow delayed updates…
 
 $ docker run -v "$PWD:/home:cached" php:7.1-cli
 $ docker run -v "$PWD:/home:delegated" php:7.1-cli
  • 68.
    Docker - Fromdevelopment to production FILESYSTEM LIMITATIONS ‣ File permissions on volumes differ between hosts types ‣ On Docker for Mac the permissions are kept to those of the running user ‣ On Docker for Linux the permissions on the host match the user:group IDs set within the container ‣ Window???
  • 69.
  • 70.
    Docker - Fromdevelopment to production SECURITY CONSIDERATIONS ‣ Kernel exploits ‣ Kernel panics within container will bring down the host machine ‣ Denial of Service ‣ Containers can hog host resources ‣ Image trustworthiness ‣ Secrets ‣ Confidential information can be stored into Docker images (e.g. in --build-args), if not careful
  • 71.
    Docker - Fromdevelopment to production SECURITY CONSIDERATIONS ‣ Patching core packages ‣ Run system updates within container? ‣ Update packages on image build, and re-build regularly ‣ Container breakout ‣ User permissions in the container = user permissions outside ‣ Namespace users (see http://dockr.ly/2wEfy2g)
  • 72.
    The End! Toby Griffiths @ToG CubicMushroom Ltd. https://joind.in/talk/51971