Sessions is temporarily moving to YouTube, check out all our new videos here.

Docker-Compose Will Change Your Life

Max Woolf speaking at HydraHack in July, 2017
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

Max will show how he uses Docker-Compose in development, and the pros of doing that.


Hi everyone. This is my quite short talk about docker-compose and how it will change your life and it's changed mine. Firstly, my name's Max Woolf, which is actually my real name. You can find me on everything online as maxehmookau. I work for a company next door, basically, called Substrakt Health. We are a spin-off from Substrakt who I'm guessing quite a few of you have heard of and I am a software engineer, though after the last talk I'm rethinking that. So, who here develops just on their machine without virtual machines, containers, anything? They just instal PHP, Ruby, whatever, and just crack on. That's what I used to do and someone showed me Vagrant, which is excellent and kinda slow. But it allows you to run a virtual machine from the command line on your own machine, so if you ever need to move computers it's a relatively easy task to do. Vagrant is excellent, everything HashiCorp make is absolutely brilliant, except it's kinda slow. It's not very portable, your VMs end up sort of gigabytes, and if someone else needs to use it, it's not actually that portable. It's not very good with Windows, although I understand it's getting better. And if you use VMWare as your sort of backing system then it's kinda expensive. And if you've using VirtualBox then it can be kinda buggy as well. So despite these failings, Vagrant is brilliant and it's made my life much easier. However, I've very much drunk the Docker Kool-Aid, so if anyone went to the last-ever Hackference last year, there was an excellent talk by Sam Wierema about Docker for dummies. It was kinda sad because it was kinda rushed. But it was really good because it someone like me, who'd been kind of ignoring Docker, thinking it's just one of these things that's gonna come and go, but it was really good to get someone actually explain to me what it was and why it was great. So yeah, I drunk the Docker Kool-Aid by the bucket-load and I spent the last year forcing it upon the development team at Substrakt. Most of them are cool with it. I use docker-compose in development. I'm talking about development, rather than production. That's a whole other topic. Its portable, even with Windows, so we've got some guys that work on Windows. It works literally everywhere, which is really nice. It actually is lightweight. As long as you've got Docker installed on your relevant system, the containers themselves are actually pretty small. And we've hired new developers recently and they've gone from zero to a full dev environment in, like, minutes, rather than hours or days. Which, when you're onboarding new hires, is really important because it can quickly show the mistakes in your onboarding process. So I'm gonna shut up and actually show it working. In your doc-compose projects, I've got just a little project I've created here. And you define a doc-compose YAML file. So, pretty standard. The version thing you can ignore, that's just the version of the software we're using. And then you just define the services key. That's it, and then you've got your development environment. In my development environment, I'm just gonna start off, just want Nginx as my server instals. And I'm just gonna run that. So on your command line you can run doc-compose up. This will be familiar to anyone who used Vagrant. And then you can see here, I've exposed port 8080, which should forward to port 80 on our server. And then, done. You can now run that on any machine that has Docker installed, Mac, Linux, Windows, whatever, and they've got Nginx in exactly the same way. And you can see, you've even got the logs here so you can see that I've just accessed it. So that's all well and good. I've got the Nginx page, which is of no use to anyone. So you can define what's called a volume, which is basically like a sink folder in Vagrant. So anything you do locally is then transferred onto your container. You kill your container, doc-compose up again. I got a blank page but that's okay. Because I've got a little website here and I've already written some HTML. Done! And that's it. And without much work you could replace Nginx for Apache if you're feeling strange. And that's it. We can expand that slightly further. So let's say I want to run MySQL. As you can see I've tried to be risk-averse in terms of live coding here. So we can have both running if we want. We'll have Nginx running on port 8080 and MySQL running on port 3333. And we've just defined an environment variable for MySQL, which is the RE password. We'll kill doc-compose again, doc-compose up. And you see it's starting MySQL and starting Nginx. So we can see our Nginx, since it's still running, but also we can connect to ... Password one, and then the port was 3333, and here's our database. And that's it, and that's fully portable will work anywhere, even on a system that doesn't have MySQL running. So you can kinda see where I'm going with this now. Let's instal WordPress, because I understand that's a popular thing. So let's just add that as a service. We'll leave Nginx and we'll leave MySQL. Doc-compose up. We've got three services now. And you'll notice WordPress starts afterwards, because we've said here that, actually, WordPress depends on MySQL. If you try and start WordPress without MySQL, you get all kinds of errors. You can see MySQL is booted and WordPress is booted, and Apache's made some complaints. I have exposed port 1000 to go to port 80 on the WordPress box. So Nginx is still running, MySQL that it read is still running, and now, please work ... WordPress is running. Again, completely portable, any operating system that runs DOCO, which is pretty much all of them now. So that is that. What else have I got lined up? Let's say for some reason I've got this system which requires Nginx to show a picture of some dogs licking a cat. MySQL to run WordPress, WordPress to run on its own, and for some reason, a Sinatra app running Ruby, which is ... I can't even remember what this Ruby app does. So we're in for a surprise. We'll bundle up, so we've got Sinatra up. Sinatra is just like a really lightweight Ruby framework. It's like Rails but with-- - [Audience Member] You've got command twice now. - I've got command command. Oh. - [Audience Member] Why don't you go through it and see what happens? - Alright. I like that. So we can ... Yeah, we've got a Sinatra app. Any Ruby devs? Hands up. No? Alright. PHP devs? Cool. It's like Silex, but for Ruby. So you define your roots here, get forward slash, output that, get forward slash puppy, picture of a puppy. So we can do doc-compose up yet again, and there you go, you get an error, because that's not valid YAML. That was risky for live coding. Thanks for putting me on the spot there. So as you can see, because I've not deleted any of these, it's booting MySQL, Nginx, WordPress, and Sinatra app all at once. And you can see here, Ruby app one, that's the thing that says we're now booted and listening on port 9292, which I've also defined here. So it's forwarding local port 9292 to the container 9292. Then WordPress is still there, Nginx is still there, and my Sinatra app is still there. And I think I defined two roots on my Sinatra app. Yep. Forward slash puppy. I never actually put a picture of a puppy. But you get the idea. You can also use it for just like ... Oh, sorry, the thing I forgot to point out here is that, with all of these three I've defined images. So Docker has built-in images for Nginx, MySQL, like all the obvious things that you'd need day-to-day. But you can also just build your own. So instead of image, you can just say build the Docker file that's local. There's a find a Docker file here, which just says it's a Ruby app, store it here, run bundle instal, which is composer instal for Ruby. And then in the doc-compose, once that's all done, run this command which boots up the web server and makes it available to anyone. So if we were to ... I'm just gonna get rid of these so we're not confusing things. Docker-compose up dash dash build, it will rebuild the container using Docker build. It will actually containerize the application. So you can put anything else you wanted here in too, if you had like, some sort of dependency, apt-get instal, if that was your thing that you needed. The possibilities are quite endless. One other thing you can do is, if you don't want to use it for services, you can also use it for just messing around with a new language that you don't particularly want to instal or trying a new version. Ruby devs use this thing called RVM which allows you to switch between Ruby versions fairly seamlessly, but I've come across problems in the past. This allows you basically to boot up a container running any version of any language you want and just have a play with it. So we'll do that. Let's go ... Ruby_two, which is using Ruby 2.3.1. Sometimes docker-compose doesn't actually stop properly. So doc-compose up, again. And you see exits because we've not told it to do anything. So it boots up the container and then closes, which is what Docker's supposed to do. So you can just run one-off containers. So say, doc-compose run dash dash rm, which deletes a container when you're finished with it. Then the name of a container, ruby_two, and then what you want to run. So we just want a bash terminal. And then here we are, inside our container. And you can do ruby v, and you can see it's the version I've asked for. And interactive Ruby, so now we've just got Ruby. And we can do what we want. But, for example, let's say, and we found this quite useful, we hear the older version of Ruby is quite a lot slower than the new version, we want to benchmark it ourselves. We'll just call this ruby_one. Docker-compose run, ruby_one, again, another bash one. We can run ruby v and you can see now we're still on Ruby 1.9.3. We've not installed anything on our local machine, this is all totally throwaway. And we're not cluttering up our machine with ten different versions of Ruby, which is a problem I repeatedly had. To be honest, Ruby 1.9.3. and Ruby 2 aren't that different in terms of what I can show you here. But you get the point. I have one final example ... Well, perhaps I didn't. No, that was all my examples I had. In which case, I will open up to questions. If there's anything anyone would like to know? - [Audience Member] In the YAML folders, could this plaintext passwords? - Yes. - [Audience Member] What is the security way of dealing with containers though, that you need passwords for? - Okay. In development, don't worry about it, in the sense of, you should be developing with a MySQL container that you just set the password to "password", and that should be fine. Because you shouldn't have live production data on your development environments, in theory. I know it's not always that simple. For production deployments, that's a whole other talk. - [Audience Member] I think ... I knew it was gonna be a pretty-- - Yeah, like we go for the twelve-factor app, we use environment variables for our secrets. Works well for us. I know there are pitfalls, but all of secret-keeping in software development is hard. And that's the best answer you'll get from me on that, I'm afraid. - [Audience Member] Have you encountered using Docker Swarm versus Kubernetes is ... - I've only touched on each briefly, to be honest, because we're sort of making the transition at the moment. I'm more excited about Kubernetes than I was about Docker Swarm, just because it's been around longer and Google are backing it, and they use it. So I kinda got a bit more faith in it, if I'm honest. But it's not based on anything other than a gut feel at the moment.