Dustin Wheeler

Hey! I'm Dustin Wheeler. I am a software developer. I love exploring new domains. Huge fan of testing. You can follow my ranting and raving at @mdwheele

Build a delivery strategy for PHP using Docker and Jenkins, Part 1

Posted on October 8, 2017 • 7 minute read

There are plenty of resources around the web that slam Jenkins together with some programming language to do Continuous Integration and Delivery for software. A quick Google search for deploy PHP application with Jenkins returns some pretty good results:

The list goes on and on. One of the problems you'll face when approaching this topic is that there is almost too much information out there on this subject and a lot of it is dated no more than a few months after publishing.

Struggling to cobble together small nuggets of relevant knowledge from 20-25 sources is a bit much to ask, I think. Sometimes we just want someone to scream, "Hey! Problem solved! Do it this way."

The problem is that "doing it this way" is always too specific. I want to solve that problem for you by teaching how to build a sane and sustainable software delivery strategy that is not specific to one application or another.

The fact of the matter is that no two applications in today's web are the same. Some applications will use Elasticsearch, MySQL, PostgreSQL, Redis, RabbitMQ, or any combination of different services. Applications place different demands on these services. Two pieces of software can use the same service in wildly different ways. I want to help you account for that in how you deliver software. I do not want you to leave this series needing to Google "How do I use Jenkins to deploy Symfony with Redis" simply because I used "Laravel with MongoDB" in my examples. Technology should have a large impact on your delivery strategy.

By the end of this series, you will:

There's probably more, but it's 2:40am where I am right now and I need to go change a diaper. I would feel bad if I left you with a whole bunch of fluff and no substance, so let's cap this post off by getting started with Installing Docker. You're going to need this for the rest of the series and it's honestly the worst part (though much, MUCH better nowadays).

Install Docker

No matter if you're running Mac OS X, Windows 10 or some flavor of Linux (Ubuntu, CentOS, Fedora, etc.) you will be able to follow along with this series. That is the core strength of Docker and host-independent containers. Go ahead and visit https://docs.docker.com/engine/installation. Find whatever operating system you're using and follow the directions to download and install the current stable version of Docker CE. Pay close attention that you are installing "Docker Community Edition".

If you are on Windows 10 Home, you'll need to install Docker Toolbox instead of the above.

While that's going, I'll explain a few things that might be different between operating systems. If you're running on some distribution of Linux, you're going to have the easiest time. That is because Docker is more-or-less a high-level driver for LXC Containers, which are supported natively by the Linux kernel. The worst thing you'll run into is making sure you're installing the "right" Docker. For example, on Ubuntu we have docker, docker.io, docker-ce, docker-engine and more. docker-ce is the officially packaged version of Docker (previously named docker-engine). docker.io is the Ubuntu repackage of upstream Docker. As long as you followed the instructions above, you should be golden. If you didn't, you'll get some version of Docker that may or may not work... at all.

So, Docker runs best on Linux, right? Pretty much, but Windows and OS X have decent workarounds and the tooling to abstract the details away from us has matured well. Docker supports Windows and OS X by running a Linux VM on your machine. Docker commands use that virtual machine as a remote Docker host. Fortunately, all of this is abstracted away from you. Recently, improvements to the Linux subsystem for Windows allow you to run Docker "natively" on Windows without needing to use Toolbox. I still use Docker Toolbox because it's what I'm used to and I don't trust the Linux subsystem for Windows with my development workflow, yet. If you're feeling adventurous, go for it. Tweet at me if you have a problem.

Docker's Installed!

So let's wrap this up by running bash on CentOS 7. Admittedly, this is much less magical if you're already running CentOS 7, so maybe try fedora instead?

Open up your "Docker Quickstart Terminal" (if on Windows) or whatever terminal you're using and run the following:

sudo docker run -it --rm centos /bin/bash
     1      2   3   4    5      6
  1. Docker! Pretty much every docker command starts with docker. Neat. Run docker by itself to see a list of commands you can execute.
  2. docker run runs a command in a new container.
  3. -it says to run the container interactively (-i) and to allocate a pseudo-TTY (-t)
  4. --rm says to remove the container once the command is exited. When you run a command inside of a container and exit, the container can stick around and be started again. It's almost like pausing. This option simply says, "When I exit bash, just remove the container."
  5. This is where we specify the name of an image we want to start a container from. There are thousands of Docker images hosted at https://hub.docker.com. You could specify ubuntu or fedora here, if you wished.
  6. This is the command we want to run. Note that some Docker images do not include a shell. Docker images are purposely single-focused so if the maintainer of the image doesn't think you need cowsay, you're not getting it!

We should see the following after running cat /etc/*-release:

[root@68db950f3dee /]# cat /etc/*-release
CentOS Linux release 7.4.1708 (Core)
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

CentOS Linux release 7.4.1708 (Core)
CentOS Linux release 7.4.1708 (Core)

Congratulations! You ran your first container. Exciting. Take a look at your prompt (root@68db950f3dee). The first part is the user you're running as. In this case, we're running as root. Some images will create non-privileged users that are used by default when running containers. Jenkins is a good example of this. The second part of the prompt is the "container identifier". Open up a new terminal and run docker ps:

$ docker ps
CONTAINER ID   IMAGE  COMMAND       CREATED       STATUS       NAMES
68db950f3dee   centos "/bin/bash"   2 minutes ago Up 2 minutes vibrant_stallman

The container identifiers match! Containers can be referred to by their identifier or by name. In this case, Docker decided to name our container vibrant_stallman because we didn't specify one.

Go back to your first terminal that is running bash on CentOS and type exit. When you run docker ps, you should see that nothing is running anymore. With that, we are done for now. I'll have another post ready about a week from now.

Welcome to my blog!

I will be posting a lot of content over the next few months across a wide variety of topics including material like you've just read. I am an aspiring writer, so if you can get past my terrible grammar, I think I have a lot of valuable ideas to share with you. If you're interested, I would really like to reach out when I publish a new article! No spam, I swear.

Go back home