The PHP podcast where everyone chimes in.

Originally aired on

August 29th, 2017

066: Docker: Drinking the Kool-Aid

After years of resisting, SammyK finally drank the Docker Kool-Aid for his everyday client work. We talk about his transition from Vagrant to Docker and some bumps he hit along the way.

with


My transition from Vagrant to Docker Show Summary


You can submit a form on phproundtable.com with any ideas you have for topics that can be discussed on the podcast.

The last episode about Docker was Episode 48.

Brand new stickers are available (much smaller!), and will be sent out for the Developer Shout-Outs.

Discussion - The panel talks about...

Docker Compose vs. Docker

Comparison:

  • You need to use Docker to figure out how Docker works. Start with this.
  • Then you use Docker Compose, because you know how Docker works by this point, so it does most of the work for you.
  • Docker Compose allows you to keep all of your configuration in a text file. With regular Docker, you need to use multiple commands to set everything up.

Minimum, you need:

  • Dockerfile
  • What container you are starting with (base container)
  • Commands to set up your configuration / install things for you

When to use the --rm flag

Docker command has multiple flags. For example:

  • -i - Interactive shell
  • -t - Allocate a tty
  • --rm - Remove container after you're done

Q: Why would you create it, only to delete it again after it's done?

Chris Tankersley:

  • He generally has an Apache container, a MySQL container, and a couple of other containers that make the application work. Those you usually want to stay around. Don't --rm those.
  • Others (composer, unit tests, etc) you will --rm ... you want to use them for something quick, but don't care about keeping them around (unlike the database container).

Phillip Shipley:

  • Will often use --rm when he's initially building his Dockerfile.
  • He can exec into a base container (or run it interactive), and have it delete itself afterwards.
  • Once it's working how he wants it to and he's finished making rapid changes to his Dockerfile, he can remove the --rm flag. It's built-in garbage collection!

Chris Fidao:

  • When you stop a container, it still exists - it's just not running.
  • If you never clean out those containers, you have this list of unused containers just hanging around in your system.

Image vs Container

Main difference:

  • You build the image (state / like an OOP Class)
  • Container is run from the image (instance / like an OOP Object)

Key points:

  • By running --rm you are cleaning up the container, but the image still exists.
  • When you make changes in your Dockerfile to copy files into the image, you want to make sure you are rebuilding the image. Otherwise, when you rebuild the container, it won't have copied those files in because it's still using the old image.

Docker Compose commands

Docker Compose settings are saved inside the docker-compose.yml file in your project root.

docker build:

  • BUILD - Build (or rebuild) the image.

docker up and docker down:

  • UP - Bring the environment up. Creates containers and starts them.
  • DOWN - Bring the environment down. Stops containers and removes them.

docker start and docker stop:

  • START - Starts services from existing containers.
  • STOP - Stops services, but doesn't remove them.

Running docker up will usually do docker build for you:

  • If the image doesn't exist, it will detect this and will build the image for you, saving the need to run docker build manually.
  • If you've made changes to Dockerfile or docker-compose.yml, it should detect this and rebuild the image for you.
  • If you've made changes to other files (e.g. your source code), it won't detect that and you need to run docker build manually before you start it up again.

Notes about adding files:

  • Copy/add files - takes place at build time, and adds them to the image.
  • You can also use volumes, which is a way of adding files to the container at runtime.
  • Official container for MySQL sets up the database on a volume. Since it's effectively mounted, the files end up on your disk.

Important distinction to make:

  • UP - Creates containers and starts them.
  • DOWN - Stops containers and removes them.
  • START - Start container only.
  • STOP - Stop container only.

So, to clarify:

  • UP/DOWN = Full environment and stack.
  • START/STOP = Just the container.

Project structure - best practices

With Docker version 2 & 3 - you can specify named volumes:

  • You can make a volume that is mountable across multiple containers.
  • Persistent outside of the containers, too.
  • By defining a named volume in your configuration file, the data will persist between up/down commands.

There is a speed drop with Windows / macOS:

  • Trying to access files from a Linux Docker container on your Windows or macOS system, it's slower. This is because the linux container boots up inside a VM.
  • Docker runs underneath the host OS kernel, it's not actually a VM in and of itself.
  • But since Windows / macOS are not linux, it bootstraps itself inside of a linux virtual machine.
  • If you need to get to stuff on your host machine, you're effectively trying to put your host machine inside a virtual machine.
  • The issue on macOS is that the layer it uses is very slow. Not an issue with Docker, it's an issue with the intermediate layer. Apple is working with Docker to speed that up.
  • Windows seems to do slightly better than macOS in terms of speed for Linux containers.
  • Linux is best of all for running Linux, because you don't need the virtualisation layer.
  • You mainly see the speed drop for I/O heavy traffic. So applications that rely on heavy I/O will suffer most noticeably.

Docker in Production

Docker as a product has stabilised significantly over the years, and is now much easier to use. It's getting better and better, and a lot of the rough edges have been "shaved off".

Production readiness:

  • Build for production
  • In your development environment, plug in what you need just for that environment.
  • You only want certain runtime dependencies like Xdebug in the environment that you need them (development). They should not exist in the production environment.

You can stack multiple configuration files on top of each other:

  • For example, docker-compose.yml (production) and docker-compose.dev.yml (development).
  • It will take the stuff in dev and then merge it into the production one.

Upcoming feature: Multi-stage builds:

  • A single Dockerfile that builds multiple images (i.e. production & development)

Multiple startup scripts:

  • You can have two separate bash scripts, one that launches with production config, and another that launches with dev config.
  • Each script can be used for a different entry point, and can do some different set up before starting the container.

Docker is greater for the state-less part of your application, i.e. your code.

Everything else should probably be pushed out to other services (Amazon RDS, Redis, etc).

Docker Machine

You can use Docker Machine with Amazon / Digital Ocean, to set up your machine.

It allows you to run things from your local machine. You can run Docker Up regardless of whether you're working on your local environment, or your production environment, which is pretty nice.

Under the hood, Docker is pretty much just a HTTP API. The Docker command is literally just an API client!

Docker Hub

A registry for storing your images. You can access public images, or you can pay to store your private images there.

On your docker server, you would then pull those images down from Docker Hub (or a similar service).

Updates could be as simple as:

  1. Stop container
  2. Docker Pull
  3. Start container

Docker Swarm

Allows you to run multiple instances quite easily, and will do the rolling release for you.

There are ways to set this up with EC2. ECS orchestration service is free, you just pay for the actual EC2 usage.

Accessing Docker via CLI

Q: Vagrant allows us to simply connect using vagrant ssh. How do we do something similar with Docker?

  • The main thing to remember is that Docker isn't a machine, it's a process. It spins up a process and then watches it.
  • You can use something like docker exec to spin up a second process in the same area, rather than SSHing into a machine.
  • They might act like machines, but they're not. There's not actually a command-line process / ssh daemon running inside those containers, usually.
  • If you change things in that container, you will lose it when you restart. The restarted container will go off the base image, so to make changes you should modify the image instead.
  • Most containers expect to run as root, they don't expect another user to run inside of them. So it's not a good idea to set up additional users.

Sub-domains / TLS in Development

  • Generally, don't bother. Just bind to a different port if you need multiple apps running at once.
  • There are ways to get things like Let's Encrypt set up locally if you need it, but on a day-to-day basis it's usually not something the panel members worry about.

Logging

  • You can run in the foreground and have it tail the logs for you, but using Ctrl+C afterwards is a little tricky.
  • It's probably better to run it in the background (as a daemon) instead using docker up -d, and then use the docker logs --follow command to follow your logs.
  • Docker most likely expects you to shut it down using docker down, not Ctrl+C.
  • If you want to get really fancy, you can push to Kibana, etc.

Sammy Kaye wraps up with

Developer Shout-Out

Thank you, Ed Finkler for your great work on @OSMIhelp! A $50 Amazon gift card from ZendCon 2017 is on its way to you.

Shout-out sponsored by ZendCon 2017

ZendCon 2017

Join the best and the brightest in PHP in Las Vegas this October.


Panelists

Phillip Shipley


Chris Fidao


Chris Tankersley


Show Notes Credit

Shane Smith

Thank you Shane Smith for authoring the show notes for this episode!

If you'd like to contribute show notes and totally get credit for it, check out the show-notes repo!