Back on December 10th, I launched by first book, Docker for Developers, on Leanpub. One of the things that I kind of glossed over, mostly because it wasn't the focus of the book, was at the the beginning of the "Containerizing Your Application" chapter. It was this:

Modern PHP applications do not generally tote around their vendor/ directory and instead rely on Composer to do our dependency injection. Let’s pull down the dependencies for the project.

$ docker run --rm -u $UID -v `pwd`:/app composer/composer install

This first initial run will download the image as you probably do not have this composer/composer image installed. This container will mount our project code, parse the composer.lock, and install our dependencies just like if we ran composer locally. The only difference is we wrapped the command in a docker container which we know has PHP and all the correct libraries pre-installed to run composer.

There's something very powerful in there that I'm not sure many people take away from the book. I spend most of my time showing how Docker is used and how to get your application into it, and the book answers the question which many people have at the outset - how do I get my application into Docker?

One thing many people overlook is that Docker is not just a container for servers or other long-running apps, but it is a container for any command you want to run. When you get down to it, that is all Docker is doing, just running a single command (well, if done the Docker way). Most people just focus on long running executables like servers.

Any sort of binary can generally be pushed into a container and since Docker can mount your host file system you can start to containerize any binary executable. In the Composer command above I've gotten away from having a dedicated Composer command, or even phar, on my development machines and just use the Dockerized version.

Why?

Less maintenance and thinking.

Docker has become a standard part of my everyday workflow now even if the project I'm working on isn't running inside of a Docker container. I no longer have to install anything more than Docker to get my development tools I need. Let's take Composer for example.

Putting Composer in a Container

Taking a look at Composer, it is just a phar file that can be downloaded from the internet. It requires PHP with a few extensions installed.

Let's make a basic Dockerfile and see how that works:

FROM php:7

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

ENTRYPOINT ["composer"]
CMD ["--version"]

We can then build it with the following:

docker build -t composer .

I should then be able to run the following and get the Composer version:

docker run -ti --rm composer

Great! There's a problem though. Go ahead and try to install a few things, and eventually you'll get an error stating that the zip extension isn't installed. We need to install and enable it through the docker-php-ext-* commands available in the base image. It has some dependencies so we will install those through apt as well.

FROM php:7

RUN apt-get update && \
  DEBIAN_FRONTEND=noninteractive apt-get install -y \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    libmcrypt-dev \
    libpng12-dev \
    libbz2-dev \
    php-pear \
    curl \
    git \
    subversion \
  && rm -r /var/lib/apt/lists/*

RUN docker-php-ext-install zip
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

ENTRYPOINT ["composer"]
CMD ["--version"]

Now rebuild the image and try again. It will probably work. You won't have a vendor directory, but the command won't fail anymore. We need to mount our directory inside of the container, which brings us back to the original command:

docker run --rm -u $UID -v `pwd`:/app composer/composer install

That is a lot of stuff to type out, especially compared to just composer. Through the beauty of most CLI-based operating systems you can create Aliases though. Aliases allow you to type short commands that are expanded out into much longer commands. In my ~/.zshrc file (though you might have a ~/.bashrc or ~/.profile or something similar) we can create a new alias:

alias composer="docker run --rm -u $UID -v $PWD:/app composer"

Now I can simply type composer anywhere from the command line and my composer image will kick up.

A better version can be found in the Dockerfile for the PHP base image of composer/composer on Github, which I based the above on. In fact, I don't build my own Composer image, I use the existing one at https://hub.docker.com/r/composer/composer/ since I don't have to maintain it.

It isn't just PHP stuff

Earlier today I sent out the following tweet after getting frustrated with running Grunt inside of Virtualbox.

It is a pain because some of Grunt's functionality relies on the filesystem notifying that a file has changed, and when Grunt runs inside of a virtual machine and is watching a mounted folder (be it NFS or anything else other than rsync) it can take up to 30 seconds for the notify signal to bubble up. That makes some slow development.

I hate polluting my work machine with development tools. I had a few people say they would love having Grunt and Bower inside of a Docker container, so I did just that.

I created a new container called dragonmantank/nodejs-grunt-bower and pushed it up as a public repository on the Docker Hub.

Since these images are pre-built I don't have to worry about any dependencies they might need, and setting up a new machine for these tools now is down to installing Docker (which is going to happen for me anyway) and setting up the following aliases:

alias composer="docker run --rm -u $UID -v $PWD:/app composer/composer"
alias node="docker run -ti --rm -u $UID -v `pwd`:/data dragonmantank/nodejs-grunt-bower node"
alias grunt="docker run -ti --rm -u $UID -v `pwd`:/data dragonmantank/nodejs-grunt-bower grunt"
alias npm="docker run -ti --rm -u $UID -v `pwd`:/data dragonmantank/nodejs-grunt-bower npm"
alias bower="docker run -ti --rm -u $UID -v `pwd`:/data dragonmantank/nodejs-grunt-bower bower"

The first time I run one of the commands the image is automatically downloaded so I don't even have to do anything other than just run the command I want.

Start Thinking about Dockerizing Commands

Don't think that Docker is only about running servers or daemons. Any binary can generally be put inside of a container, and you might as well make your life easier by making your tools easier to install and maintain.

OK, so the title sounds like it comes off as a bit harsh. Today it was announced that RogueWave Software aquired Zend, and RogueWave could now offer and support a full LAMP stack that many enterprise customers were already running. Zend is a staple in the PHP community, with it's founders Andi Gutmans and Zeev Suraski working on the Zend Engine (the thing that turns all of our PHP code into something useful), and Zend's suite of software including Zend Framework, Zend Server, and Zend Studio.

Looking at RogueWave, Zend's software will be a good compliment to what RogueWave already offers. So congrats to both parties.

Let's not stop Twitter though, and my timeline thus far is filled with congratulations all the way to doomsday predictions on the future of PHP. Let's break down what I think will happen.

Zend as they are will disappear

From what I've seen of traditional enterprise mergers, we've got a good two to three years before we start seeing anything major. There is traditionally a grace period where the newly aquired company is allowed to function like they had for a few years as everyone figures out what is going on, especially when the aquisition is amicable. Zend will continue to look like Zend for a while.

After that grace period wears off, we'll start to see changes I'm sure. Zend software will start to be licensed like however RogueWave's software is licensed, release schedules will start to match up, synergies between projects will be more heavily looked at, and so on. Whether any of that is good or bad I don't know, I know little of RogueWave personally, but Zend isn't going to stop acting like Zend overnight.

I hope that anyway. I'm looking forward to a few more ZendCons in Vegas.

The Zend Engine will change licenses

PHP, and the Zend Engine, currently follow the PHP License. There's a line at the top though that has people worried:

Copyright (c) 1999-2006 Zend Technologies Ltd. All rights reserved.

Zend holds the copyright to the Zend Engine, and thus the ability to set the license on the Zend Engine. What's the Zend Engine? It's the thing that makes PHP... well, PHP. It turns our written code into something servers understand, and makes things work. The only major player that compares to it is HHVM (yes, there are others, but HHVM is the only one I've seen with real traction).

So, as copyright holder, Zend/RogueWave is well within their rights to change the license to something more permissive, or lock it down. It is their choice.

If they do decide to do that, they can't change it retroactively. The PHP Community as a whole can continue to use previous versions of the Zend Engine, as long as they continue to follow the PHP License, and ignore the "new" Zend Engine. Life would find a way.

There's precedent for that in fact, as when Zend suddenly showed up with phpng, there was some talk about not using it. We're a fickle group, and PHP internals could, and would, move away from the Zend Engine if needed. We'd also gladly continue to use older versions of Zend Engine before the license change.

Worse case, we're all switching to HHVM and we have a few minor bugs to figure out.

Licensing Changes [EDIT - 2015-10-06 2:05pm]

A few people have brought to my attention my mistating that Zend can change the license. It's more complicated then I let on above, but as the copyright holder to the Zend Engine Zend could change the license. This will take a bit of work though, because in PHP each contributor keeps copyright over the code that they themselves have writtern. By contributing code to PHP, we don't really have one specific copyright holder, anyone that has contributed has a bit of say over the license change.

To top that off, everyone would have to agree to the license change. Joomla went through a similar process when they tried to change the license on the Joomla Framework code to LGPL. This meant determining who contributed under the old licenses and getting them to sign off on the new license. It was a tremendous undertaking, but they did it.

So, Zend has the copyright on the Zend Engine, and can attempt to change the license, if everyone agrees. I don't forsee that happening. I'd bet we'd replace the engine long before that happens.

For a bit of a doomsday scenario, I wouldn't rule out the possibility of a new engine from RogueWave that is compatible with Zend Engine/Whatever we use in the future, much like HHVM is. HHVM has already proven that there is a market for an enhanced PHP that is compatible with Zend Engine PHP but has some nice things added. That would allow RogueWave to offer an "enterprise PHP" to their customers that they control, much like we see Oracle roll their own version of Redhat.

If this happens, I hope RogueWave calls it the "Rogue Engine." RogueWave, feel free to contact me for payment on the usage of that name.

Zend Framework will die

No it won't. Zend Framework, while a nice entry point for developrs to get into Zend's over-arching product line, is an open source project. Anyone can fork it and work on it. Zend Framework is also a major player in the PHP Framework space, with a vibrant community and a huge userbase. Granted, the main contributers to Zend Framework are Zend employees, but the license is permissive and I'm sure that people will still work on it in the event of RogueWave no longer wanting to support it.

RogueWave seems to invest heavily in Open Source software though, and Zend Framework will work well with their customers. I doubt the future of Zend Framework is anything to worry about.

So, Congrats to RogueWave and Zend

I, for one, want to congratulate Zend and RogueWave on their partnership and merger. They seem to compliment each other, and it just means that PHP will get better support in enterprises.

In a few years I might eat my words, but I'm sure right now my friends at Zend will enjoy themselves going forward.

Earlier today, Juan Treminio sent out this tweet, and I injected myself into the conversation.

The short and the long of it was Windows hampering web developers because of some lacking functionality, namely Linux file permissions, a proper CLI, tooling, etc. Linux and OSX have great tooling and setups that are familiar to developers, and Windows falls short.

I respectfully disagree with Juan on this. I've been working as a web developer on Windows for years, though I will gladly admit that there are things that I miss from Linux and OSX (and I'd even go so far as to say I'd rather just use Linux than OSX for general web development). Of course, I run Linux servers and am a Linux sysadmin, and I have a MacBook Pro. I don't consider myself a fanboi of any OS (and not that I think Juan is one either).

In an effort to show that Windows doesn't really have as many shortcomings as it seems, I'll document my setup and pitfalls that there are.

The Command Line - Powershell

I spend most of my time in Powershell. It's always open. Now, I'll admit that Powershell is not anywhere near as nice as an actual Unix terminal, but most of that is because of the way that it handles text selections, and it's inability to actually go full screen. This does not hamper my ability too much and there are ways to make it better, which I've done.

First and foremost, I install git from http://git-scm.com/ and let it add itself to my path. I don't add the full GNU toolset, just git and it's associated stuff. Now I can use git from Powershell just like Linux and OSX. git clone and all the git functionality is there.

I usually add the bin directory of git to my PATH after, this way I can get ssh access directly from Powershell. You may get some weirdness SSHing some servers since Powershell (and CMD) act slightly different than a traditional shell, so keep that in mind. I've seen apps like vim or screen not behave correctly as Powershell doesn't handle resizes or screen clears properly through SSH. It's minor, but it can happen.

Part of the reason OSX and Linux have such a great command line experience is not completely because of the terminal itself, but because of the tools behind it. Unix operating systems tend to ship with either a BSD or GNU suite of tools like grep, sed, awk, etc, that make working with text files and the system much nicer. Powershell does have some of these same things built in, they just aren't named the same. They also work a bit differently than GNU/BSD toolsets, so I normally install GnuWin32.

There is also cygwin. I have a love/hate relationship with cygwin. Most of the time I end back up at Powershell. You might try it out, but don't think it's the end-all-beat-all of terminals on Windows.

I would also recommend learning Powershell in general. It can do many basic things that are found in the GNU/BSD tools, like grep. The commands are just different. When in doubt, google for it and you'll probably get something back. Worse case, use GnuWin32.

As for other Powershell goodies, look into extensions like posh-git. This makes working with git in Powershell much nicer. There's a ton of extensions available for PsGet, so I would browse it's directory for things you might find useful.

Using PHP

There is a lot of things we do as PHP developers that are just glorified PHP scripts. PHP has had native Windows builds for a long time, and it generally works just fine. Head over to http://windows.php.net/, download the latest Non Thread Safe version, extract it somewhere (like c:\php56), and append it to your PATH. You now have PHP available in Powershell.

If you need to modify it, copy a version of the php.ini that the download has and enable different extensions that PHP comes with by uncommenting them.

If you need an extension that doesn't ship with PHP... you might be out of luck. If you need to compile extensions on Windows manually you're going to need Visual Studio, all the correct libraries, and some crossed fingers. Most of the projects I work on generally do not cause me to need to install extensions in Windows directly, most of them are running in vagrant.

Most PHP scripts work just fine in Powershell using PHP. I use Composer all the time, and even the Sculpin phar works. drush used to have some issues but it's rare whenever I'd run that directly under Windows. Your mileage may vary.

IDEs and Text Editors

Time to start the flame wars.

For Windows, my two go-two things to write code are PhpStorm and Sublime Text 3.

I use PhpStorm only because it works well for what I do. Getting xdebug to work with a vagrant box is normally easy, and it has a lot of conveniences that work for me. There isn't anything wrong with other IDEs like Zend Studio, I just like PhpStorm better.

Sublime Text does have a release cycle that is outpaced by glacial movements, so I've also been looking into Atom and Visual Studio Code. Atom is OK, but I find it stalls pretty frequently and is very CPU heavy no matter what I'm doing. Visual Studio Code is nice but exists in this weird area where it's more than a text editor but not a full IDE for PHP, so it lacks. Neither handle huge files well, so I keep coming back to Sublime Text.

I will say that, while I love vim, it's not so great on Windows, so I don't use it there. I use it all the time on Linux and OSX though, but the Windows experience isn't there. Sublime Text is miles ahead.

Development Stacks

It's vagrant. There's nothing special there. Since I have git and SSH available through Powershell I can use vagrant ssh, but vagrant has always worked well for me under Windows. My only complaint is only having SMB mounting support for shared volumes. NFS doesn't work, and I've never gotten vagrant to recognize when I have rsync installed.

Install Virtualbox and vagrant like normal. Develop like everyone else. When you have stuff that needs to run under Linux, SSH into the VM and do it there. This is not any different than when I work on Ubuntu or OSX. I do almost everything for my project inside the VM, even if I have everything installed in the host OS.

If you really want to, you can install your database locally and use IIS Server. There is nothing wrong with that, especially since IIS 7. PHP works great with it. I don't deploy to Windows though, and vagrant is pretty much the standard nowadays.

Don't use a *AMP stack like XAMPP or WAMP though. They won't replicate developing on a Linux machine and can have their own weird quirks. Just use vagrant.

Other Random Stuff I use

The above takes care of almost everything I do day to day. I use HexChat for IRC, which connects to a ZNC server sitting on an Ubuntu box. I use the venerable PuTTY when I need a better SSH client than Powershell. Slack has a Windows client now, so I'm connected through the various Slack teams I'm in. I still use FileZilla (the version without all the crapware) when I need a graphical interface for FTP or SFTP.

And I'm Happy

That's about it. I spend almost all day in Powershell, PuTTY, and PhpStorm and I get all my work done without any hassle. It's not Linux, and I'd rather run Linux 24x7 if I could, but I don't. I can, and sometimes do for short periods of time. When I travel, I take a Macbook Pro with me because it has way better batter life than most of the Windows laptops that I've had.

I know many PHP developers that happily use Windows as well. It doesn't make us any less productive as developers. It doesn't make us any better as developers either. Every developer finds a toolchain and workflow that works for them. This is my Windows toolchain. I hope whatever toolchain you use works well for you.