How can I develop a LAMP web application using Docker, Puppet and Vagrant?
Solution 1:
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
Solution 2:
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.