71
votes

In the dark ages, my usual setup for development of LAMP web applications was to test locally on my machine. PHP (in my case), the database and the web server were all installed natively.

The server was set up with standard installs of Apache and MySQL, and I had multiple virtual hosts for different parts of the web application. When I was happy with the results I had on my local machine, I'd logged into the server and did git pull in the staging environment.

Assuming everything was working as well on the server as it was on my machine, I'd do the same thing for production.

New beginningsā€¦

So now I'm starting a brand new web application from scratch, and I want to do it "the proper way". I've read up about Docker, Vagrant and Puppet (and Chef, although I personally prefer Puppet's system of dependencies rather than Chef's iterative process). Despite all the research I've done, there still seem to be several questions I can't seem to find answers for:

Should there be separate Docker containers for the web server (such as Apache), the database server (such as MySQL) and each part of the web application?

When I talk about parts of the web application, I mean things like mysite.com, controlpanel.mysite.com, etc. These "parts" will share the same database.

Since Docker seems to provide ready-made containers for things like the web and database servers, it seems like those things at least should be in separate containers. Should the different parts of my web application be in separate containers, too?

Docker containers seem to be designed to be replaceable rather than me having to update the software inside them. What about the data they write that I don't want to lose?

The database server will manage files related to the content of my database (that I'll want to be backing up). The web server will be creating logs, and my web applications will be managing various files and caches, etc. All these files need to be written outside of the application's containers (because I might replace them when updating?), so where do they go? Straight into the host machine's file system? Or into a separate "Docker Volume"?

If they go into Docker volumes, should I use a separate volume for the database, web server, application, etc.? Can I still easily access the contents using SFTP from my local machine like I do now? I don't want to lose any convenience here!

Is it a good idea to use Puppet to create and manage the Docker containers, both for the development server and production server?

It seems Puppet has support for managing Docker containers directly, so this seems like a reasonably good way of easily setting up a server or the production environment (using Vagrant) from scratch.

Hopefully I've asked some relevant questions; it would be great to get some proper "best practices" for development and production of LAMP-like web applications. it's just there doesn't seem to be much that I've found!

2

2 Answers

47
votes

Should there be separate Docker containers for the web server (such as Apache), the database server (such as MySQL) and each part of the web application?

There is no correct answer to that question. If you will be using Docker in production, then try to run your Docker containers in your development environment as they will be in production. Else just use the Docker containers the easiest way you can.

Docker Hub provides ready to go containers for PHP, databases, etc. and it is easy to use them. On the other hand, you have to link them together to allow them to interact. For a development environment and if you use multiple containers, I would advise to use docker-compose.

Another path is to build a Docker image that is the closest to your production machine (assuming you have only one machine) which would run the database, the web server, and PHP. A container from such an image would have to run multiple processes. This can be achieved in different ways. Take a look at supervisor or phusion/baseimage.

When I talk about parts of the web application, I mean things like mysite.com, controlpanel.mysite.com, etc.

You could have them separated. If those applications need to share sessions, make sure sessions are stored in database or on a docker volume that is accessible to all.

Docker containers seem to be designed to be replaceable rather than me having to update the software inside them. What about the data they write that I don't want to lose?

Docker has a thing called volume to allow data to be written on a filesystem out of the container. There are different ways to work with volumes: you can mount a directory from the Docker host to a container volume, or you can have data volume containers, or named volumes.

Docker volumes are an important concept and it is worthwhile to take the time to master them.

If you want to easily access the data used by your containers from your Docker host, mounting a directory on the Docker host is the way to go. Although it may be tricky regarding permissions and ownership of the files.

Regarding backups, take a look at the Docker user guide where everything you need to know in regards with volumes is detailed.

Is it a good idea to use Puppet to create and manage the Docker containers, both for the development server and production server?

The best practice is to operate on your development environment the same way you will operate on your production environment. There is no point going through setting up Puppet correctly for your development environment if all that work won't be used for the production environment. Having a Vagrantfile that provision a VM with Docker is really easy with just shell provisioning ; IMHO puppet/chef/... are overkill.


You are asking the right questions, but there isn't any answer that fits all situations. In my view there are two ways to do things:

  • make your development environment replicate exactly your production environment
  • make your development environment different from production, keeping it as simple and straightforward as you can so developers won't feel the friction induced by using new tools
13
votes

While the answer of Thomasleveil is already very good and covers all important parts, I'd like to add some additional points.

Vagrant, Puppet/Chef and docker-compose

When you're provisioning a virtual machine with Vagrant you usually use Puppet or Chef to install the required packages for your server ... along with a few shell scripts. PuPHPet is an excellent source for configuring a virtual machine-based LAMP Stack and learning how Puppet and Vagrant work together in a bit more complex setup. An alternative is Protobox by the way.

When you're using Docker containers with Vagrant in the same way like you do it with VMs. Then with vagrant up you're essentially running Docker containers with the Docker provider. Vagrant will build the containers for you from a Dockerfile or use an existing image, more or less like docker-compose (fig) and run them.

A major reason to choose Vagrant for your Docker setup is, if you or your team is partially working in a Windows environment, since Vagrant allows you to keep your setup consistent, no matter what your host system is (see Host VM).

If you're on OS X, you can use docker-compose with the VirtualBox VM, and if you're on Linux you can use Docker natively. It is also always possible to log in to the boot2docker (or another Docker Host VM) via ssh, no matter if you're on Windows or OS X.

Note: You should not SSH into your containers, but that's another topic.

As of February 2015

docker-compose feels a bit snappier to me and also handles starting, stopping and rebuilding containers more efficiently.

Vagrant has the advantage to specify a different host VM, e.g., per project, if you prefer such a setup.

Note: there's also a Docker provisioner which is more related a Puppet build process.


Should there be separate Docker containers for the web server (such as Apache), the database server (such as MySQL) and each part of the web application?

When using Docker containers you're basically running single, isolated processes. The usage of a supervisor should be avoided) and is also not needed for a LAMP stack.

So my answer is definitely: Yes, there should be separate containers!


When I talk about parts of the web application, I mean things like mysite.com, controlpanel.mysite.com, etc.

This depends on your needs. I suggest you to read 12factor application documentation, which describes the important things to take care of in a very detailed way.


Docker containers seem to be designed to be replaceable rather than me having to update the software inside them. What about the data they write that I don't want to loose?

In addition to @Thomasleveil's answer, I'd recommend you also a separate storage backend for user uploads like Amazon S3, SFTP, or WebDAV.

In my opinion, your web application container should be treated like a client application, accessing your database and storage backends (services) and not rely on data from volumes when running in a production environment.


Is it a good idea to use Puppet to create and manage the Docker containers, both for the development server and production server?

I don't know about the orchestration capabilities of Puppet, but for building containers, if you're using Vagrant I see no need for Puppet, because of the native Docker provisioner of Vagrant.


Bonus

For all those things described above, you can have a look at my 12factor PHP application template based on Yii 2.0 Framework with a dockerized LAMP stack. With Docker you can also easily plug-in reverse proxies or selenium testing containers into your project, because they exist as pre-build images and can be downloaded and configured in a few minutes and started in seconds.