1 00:00:04,600 --> 00:00:10,360 ‫This section is going to focus exclusively on Docker Compose, which is a combination of a command line 2 00:00:10,360 --> 00:00:17,710 ‫tool and a configuration file. Requirements for this section are that you really need to know a lot of the fundamentals 3 00:00:17,770 --> 00:00:24,720 ‫from the last few sections around images and containers. 4 00:00:24,730 --> 00:00:29,080 ‫As we're going through this course, you're probably going to start to hear me get more and more excited 5 00:00:29,110 --> 00:00:32,390 ‫because things just keep getting better. 6 00:00:32,470 --> 00:00:32,780 ‫Right? 7 00:00:32,800 --> 00:00:39,000 ‫As you learn one component, you're thinking, 'man, bind mounts and volumes are really cool. That's going 8 00:00:39,000 --> 00:00:41,970 ‫to save me some time. I can imagine how I'm going to use that. Blah blah blah blah. 9 00:00:41,980 --> 00:00:47,220 ‫Then, I'm going to come with the next thing that's going to be even better than what you just learned. 10 00:00:47,230 --> 00:00:49,610 ‫In this case, it couldn't be more true. 11 00:00:49,630 --> 00:00:55,810 ‫Docker Compose. So, what is it? And why do we care? So few software services are truly standalone. 12 00:00:55,810 --> 00:01:00,430 ‫When you think about your containers, they're a single process solution, and we're rarely going to use just 13 00:01:00,430 --> 00:01:04,160 ‫a single container to solve a problem or provide a service to our customers. 14 00:01:04,240 --> 00:01:10,510 ‫Our containers will often require other containers such as SQL or a key value. And other applications 15 00:01:10,510 --> 00:01:15,880 ‫that we'll need to run in containers, like proxies or web frontends or backend workers, and so on. 16 00:01:15,880 --> 00:01:20,680 ‫What if we had a way to connect all those pieces of our solution together, where we didn't need to 17 00:01:20,680 --> 00:01:26,830 ‫remember all of our docker run options, and then get them into discreet, virtual networks with relationships 18 00:01:26,830 --> 00:01:33,370 ‫between them, and only expose the public ports, and then spin them all up and tear them down with one 19 00:01:33,370 --> 00:01:34,230 ‫command. 20 00:01:34,600 --> 00:01:36,370 ‫Well, that's Docker Compose. 21 00:01:36,730 --> 00:01:40,630 ‫Before we dive in, we need to clear up that there's two parts to 22 00:01:40,630 --> 00:01:46,860 ‫Docker Compose. The first part is the YAML file and it's super simple to understand. 23 00:01:46,870 --> 00:01:52,000 ‫It's written in YAML, and if you've never dealt with YAML, that is a very easy configuration language. 24 00:01:52,000 --> 00:01:54,360 ‫It's almost as easy as an INI file would be. 25 00:01:54,360 --> 00:01:57,340 ‫I actually think it's easier because it shows hierarchy. 26 00:01:57,340 --> 00:02:02,590 ‫We'll dive into that. That file is where you would specify all the containers you need to run, the 27 00:02:02,590 --> 00:02:08,710 ‫networks you need, any volumes you might need, environment variables, images, and all sorts of other configuration 28 00:02:08,710 --> 00:02:09,440 ‫options. 29 00:02:09,670 --> 00:02:16,600 ‫Then the second part of Docker Compose is a CLI tool, which is docker -compose, that we use normally 30 00:02:16,600 --> 00:02:25,980 ‫for just local dev and test, using that YAML file we created to simplify our Docker commands. 31 00:02:26,010 --> 00:02:28,570 ‫Let's talk about that Docker Compose file. 32 00:02:28,590 --> 00:02:34,590 ‫There's actually versions to the things that you can put in the compose file. So when Docker Compose 33 00:02:34,590 --> 00:02:39,630 ‫was created years ago, it was actually called "Fig" and it was just assumed version 1. It didn't actually 34 00:02:39,630 --> 00:02:45,600 ‫even list a version in the file. As it's matured and added new features to what the file can have in 35 00:02:45,600 --> 00:02:52,080 ‫it, such as networks and volumes, they have created the version statement, which is actually the first 36 00:02:52,080 --> 00:02:57,240 ‫line in the file. This file can actually be used with a Docker Compose CLI, which we'll talk about 37 00:02:57,240 --> 00:02:57,800 ‫in a minute. 38 00:02:57,900 --> 00:03:03,960 ‫This is, again, mainly for local development management and just making it easier to get around in 39 00:03:03,960 --> 00:03:06,270 ‫your environments on your local machine. 40 00:03:06,390 --> 00:03:13,560 ‫Now, starting with the beginning of 2017, we have version 1.13 and anything beyond that, these files 41 00:03:13,560 --> 00:03:19,400 ‫can now be used directly with the docker command line in production with swarm. Of course, there's 42 00:03:19,420 --> 00:03:22,310 ‫great help at the command line with the --help. 43 00:03:22,480 --> 00:03:27,310 ‫As we look at some of the examples, know that the Docker Compose file is a default name, but you 44 00:03:27,310 --> 00:03:33,460 ‫can actually use any file name you want, as long as it's proper YAML and that you use the -f to specify 45 00:03:33,460 --> 00:03:34,950 ‫which file you're trying to use. 46 00:03:36,510 --> 00:03:43,070 ‫If I open up my editor and look at the template here, I just wanted to show some of the outline of what this 47 00:03:43,370 --> 00:03:44,800 ‫is supposed to look like. 48 00:03:45,050 --> 00:03:47,610 ‫We have the version value in the beginning. 49 00:03:47,690 --> 00:03:51,990 ‫The newest version in the first quarter of 2017 is 3.1. 50 00:03:52,220 --> 00:03:57,110 ‫But I always make it at least version 2. If you don't add that line there, it's always assumed to be version 51 00:03:57,110 --> 00:03:57,400 ‫1. 52 00:03:57,410 --> 00:04:00,220 ‫But I don't recommend that because you lose a lot of the features. 53 00:04:00,530 --> 00:04:05,420 ‫So I typically start with version 2. Then if I need specific features out of version 3 and 3.1, 54 00:04:05,420 --> 00:04:11,270 ‫I end up typing the version number in there. You'll see the other three main sections are services, 55 00:04:11,480 --> 00:04:14,070 ‫volumes and networks, right? 56 00:04:15,370 --> 00:04:16,940 ‫So, this is hierarchial. 57 00:04:17,140 --> 00:04:22,860 ‫Under services, everything can be two or four spaces, but it does need to be consistent. 58 00:04:22,860 --> 00:04:27,610 ‫If you just look up YAML on the internet, you'll find some sites that guide you with the specifics of 59 00:04:27,610 --> 00:04:28,870 ‫how to format this file. 60 00:04:28,900 --> 00:04:33,610 ‫If you're using a modern editor, it's going to actually speak the YAML language and know how to deal 61 00:04:33,610 --> 00:04:35,110 ‫with these files and their formatting. 62 00:04:35,110 --> 00:04:41,550 ‫Usually, here, you have, at a minimum, services, which is really just containers. 63 00:04:41,560 --> 00:04:45,730 ‫The reason they actually call them services is because each container that you create in here, you could 64 00:04:45,730 --> 00:04:49,870 ‫actually have multiple ones of those containers for redundancy. So they needed to come up with a different 65 00:04:49,870 --> 00:04:50,510 ‫word. 66 00:04:50,590 --> 00:04:54,100 ‫I think services is great because that's basically what you're doing. Right? 67 00:04:54,100 --> 00:04:59,440 ‫Each container, or containers, that are identical, that you're using are usually providing a service to 68 00:04:59,440 --> 00:05:00,100 ‫something. 69 00:05:00,310 --> 00:05:03,640 ‫Underneath the service name, and again you can call it whatever you want. 70 00:05:03,640 --> 00:05:07,750 ‫It doesn't have to be the name of the image or it doesn't have to be anything related at all. 71 00:05:07,750 --> 00:05:13,900 ‫It could be Barney for the service name, but it will be the DNS name, that we'll find out later, is used 72 00:05:13,930 --> 00:05:16,170 ‫inside of your Docker networks. 73 00:05:16,180 --> 00:05:20,090 ‫Similar to when you give the --name to a docker run command. 74 00:05:20,320 --> 00:05:26,500 ‫Here, I've shown that we can optionally specify the image. We can specify the alternate command to 75 00:05:26,530 --> 00:05:31,870 ‫run. If we wanted to overwrite the actual command that was specified in the image when we run it, 76 00:05:31,990 --> 00:05:33,240 ‫we can do that here. 77 00:05:33,430 --> 00:05:37,720 ‫Basically, all the things we do from the docker run command, we can save them here. Because that's 78 00:05:37,720 --> 00:05:42,880 ‫what really this is about, is taking all of the work out of remembering all the different things in 79 00:05:42,880 --> 00:05:45,790 ‫docker run command for those things you're running constantly. 80 00:05:45,790 --> 00:05:49,780 ‫If you have your own development environments, or your own tools, you probably don't want to type those 81 00:05:49,780 --> 00:05:53,120 ‫commands over and over. And shell scripts can only do so much. 82 00:05:53,140 --> 00:05:53,770 ‫Right? 83 00:05:53,800 --> 00:05:59,380 ‫So, this file would actually replace a shell script that would automate your docker run commands. 84 00:05:59,380 --> 00:06:00,840 ‫This is a much better way to do it. 85 00:06:00,850 --> 00:06:03,520 ‫It's easier to read and it's better documented. 86 00:06:03,520 --> 00:06:05,620 ‫You'll notice that spaces in here are allowed. 87 00:06:05,740 --> 00:06:08,020 ‫You can have spaces in comments wherever you want. 88 00:06:08,020 --> 00:06:11,380 ‫If you had multiple services, you just need to make sure they're unique names. 89 00:06:11,500 --> 00:06:16,320 ‫Then, the other parts that we specify are volumes and networks. And again, these are optional as well. 90 00:06:16,480 --> 00:06:19,950 ‫It's basically the same rules as when you're running from the command line. 91 00:06:19,960 --> 00:06:24,700 ‫If you were to ever need to use the docker volume create or the docker network create commands, and 92 00:06:24,700 --> 00:06:26,040 ‫again, you don't always have to. 93 00:06:26,050 --> 00:06:27,960 ‫It just depends on your situation. 94 00:06:28,240 --> 00:06:29,610 ‫You can put them here as well. 95 00:06:29,620 --> 00:06:32,390 ‫Let's look at a real world, simple example. 96 00:06:32,440 --> 00:06:39,160 ‫You remember in the last section, we had a lecture where we used Jekyll really quick to just do a bind 97 00:06:39,160 --> 00:06:40,300 ‫mount example. 98 00:06:40,420 --> 00:06:45,750 ‫So this is what the compose file would look like for that docker run command, and you'll see that I have 99 00:06:45,750 --> 00:06:47,290 ‫specified the image here. 100 00:06:47,290 --> 00:06:49,460 ‫I've named it Jekyll. 101 00:06:49,570 --> 00:06:56,650 ‫I've given it a volume. You'll notice instead of using the pwd, Compose actually understands the dot, 102 00:06:56,680 --> 00:06:59,740 ‫meaning this is the current working directory I'm in. 103 00:06:59,770 --> 00:07:06,900 ‫Just use this directory that I'm running the compose file from. Then the ports or the -p option. 104 00:07:07,010 --> 00:07:12,140 ‫You'll notice some little things about YAML, where when something only has one option, like if there's only 105 00:07:12,140 --> 00:07:18,020 ‫going to be one image for each service, it would usually be a key and value format like this. 106 00:07:18,140 --> 00:07:22,940 ‫If it's going to be a list of items, like volumes and ports where you can have multiple ones, you'll notice 107 00:07:22,940 --> 00:07:29,590 ‫that the compose file usually has a plural. Instead of volume, it's volumes. And instead of port, it's ports. 108 00:07:29,810 --> 00:07:33,100 ‫And then there'll be a list format with a -. 109 00:07:33,390 --> 00:07:36,170 ‫If we jump into another example real quick. 110 00:07:36,170 --> 00:07:38,330 ‫You'll see that in this one, 111 00:07:38,330 --> 00:07:44,150 ‫this is actually a sample WordPress setup where you have the database service down here that's running 112 00:07:44,150 --> 00:07:45,620 ‫a database container. 113 00:07:45,710 --> 00:07:50,130 ‫And then the WordPress web server container up top. 114 00:07:50,360 --> 00:07:54,620 ‫You'll notice a little thing that's different about this one is that we're using the environment 115 00:07:54,620 --> 00:08:00,830 ‫variables, which would be the same as a -e at the command line. But instead of a list format where 116 00:08:00,830 --> 00:08:02,380 ‫we have a -, 117 00:08:02,480 --> 00:08:05,740 ‫this is, again, another key and value statement. 118 00:08:05,750 --> 00:08:11,070 ‫In this format, we don't use the -, we just list the key and the value. 119 00:08:11,150 --> 00:08:17,270 ‫If I needed to add another one, I would just do that here. All of these would be passed into the 120 00:08:17,270 --> 00:08:21,230 ‫container, when it runs, using the compose command line. 121 00:08:21,230 --> 00:08:26,330 ‫Then lastly, we have one more example. This one is a little more complicated. It's actually one I 122 00:08:26,330 --> 00:08:34,030 ‫was working on recently to set up a three-database server cluster behind a Ghost web server. 123 00:08:34,190 --> 00:08:38,930 ‫Ghost is actually a blog system similar to WordPress. You'll see that I have multiple environment 124 00:08:38,930 --> 00:08:41,960 ‫variables for each one of these containers. 125 00:08:41,960 --> 00:08:48,320 ‫So I've got my Ghost container up top. Then I actually have this thing known as a SQL Proxy, which 126 00:08:48,320 --> 00:08:55,000 ‫it sits in front of MySQL servers and acts as a load balancer and failover solution. 127 00:08:55,010 --> 00:09:02,720 ‫Then I have each of my two, MySQL servers. You'll notice another option down here that says, 128 00:09:02,720 --> 00:09:06,130 ‫'depends on,' and depends on is a pretty common one. 129 00:09:06,140 --> 00:09:12,050 ‫It basically helps Compose understand the relationship between these services. It knows that if I 130 00:09:12,050 --> 00:09:17,120 ‫need to start my Ghost one, then I also need to start other ones as well. 131 00:09:17,120 --> 00:09:21,890 ‫You can see up here that my Ghost one actually depends on these. We'll get into the details of how 132 00:09:21,890 --> 00:09:24,100 ‫this works in later lectures. 133 00:09:24,200 --> 00:09:29,180 ‫But for now, this is probably a lot to digest, and all these different commands and whatnot, but trust 134 00:09:29,180 --> 00:09:35,330 ‫that Docker has some really great documentation on their website. If you just look for Docker Compose 135 00:09:35,330 --> 00:09:38,640 ‫file on Google, you'll probably find this with the first couple of hits. 136 00:09:38,660 --> 00:09:44,390 ‫It's going to be under the docs.docker.com website, as usual, and it's going to be documentation 137 00:09:44,390 --> 00:09:49,100 ‫about every single little key and value option you have. 138 00:09:49,100 --> 00:09:56,490 ‫You'll see the depends on I just mentioned. You'll see environment here where it shows different ways 139 00:09:56,490 --> 00:10:00,360 ‫to put in environment variables. What's great about this documentation is it gives you plenty of 140 00:10:00,360 --> 00:10:01,360 ‫examples. 141 00:10:01,380 --> 00:10:09,540 ‫Personally, I'm on this site every day, just like I'm on the docker run command options page or the compose 142 00:10:09,540 --> 00:10:10,900 ‫command options page. 143 00:10:11,040 --> 00:10:15,750 ‫I'm constantly referencing these because there's just frankly so many features nowadays that I can't 144 00:10:15,750 --> 00:10:16,670 ‫remember them all. 145 00:10:16,830 --> 00:10:20,280 ‫So I keep them close in my bookmarks. 146 00:10:20,350 --> 00:10:25,390 ‫Now that we have a general idea of what the compose file format might look like, let's jump over to 147 00:10:25,390 --> 00:10:28,680 ‫the command line and learn about the Docker Compose CLI tool.