In this section, we've covered a lot about Swarm. Swarm, Stacks and Secrets are kind of like a
trilogy of awesome features that can really make things much easier in production for us.
I want to show you what it might be like if you actually took your Compose files, organize them in
a couple of ways,
and this is what I basically call living the dream.
It turns out you can actually use a single file to do a lot of things, but sometimes your complexity
grows and you're going to need multiple Compose files.
I want to just run through real quick.
You don't actually have to do this yourself if you don't want to. I'm just going to show you an example of
how these Compose files might work together to build up your environment as you go.
In this scenario, we're going to use docker compose up for our local development environment.
We're going to use a docker compose up config and file for our CI environment to do integration testing.
Then when we're in production, we're going to use those files for docker stack deploy to actually deploy
the production environment with a stack. So, I'm on my local machine and we're going to be using the example
before of the Drupal scenario, with a database server, and a web frontend.
We have the Dockerfile we have used in our previous assignments. We're rebuilding a custom, yet simple,
drupal config with a template.
Then we're going to have this default compose file.
This is called an override,
what we're about to do. An override is where I have the standard Docker Compose file, and it sets the
defaults that are the same across all my environments.
Then, I have this override file that by default, Docker Compose, if it's named this exact name, docker
compose.override.yml, it will automatically bring this in whenever I do a docker compose up.
You'll see that in this scenario, we're assuming local development because we really want the hand-typed
commands we're going to type to be easiest locally.
Normally in your CI environment, it's all automated so we don't really care if those commands are
a little bit longer.
But we really want locally is the easy docker compose up.
The cool thing is Docker Compose will read this file automatically and it will apply this over
top, or override, any settings in the Docker Compose yml file.
And so here,
notice I don't have the image name, because that's already specified over here. In this override file,
I override by saying I want to build the image locally using the Dockerfile in this current directory.
I want to create a port on 8080 for local development. And I'm setting up some volumes, and you'll even notice
I gave you an example here of a bind mount, where I might be doing a custom theme. And I want to mount
my theme on my host into the container like we did in previous sections, so that I can change it locally
and then see it right away on the server.
And by the way, for this example, I don't actually know how to develop themes in Drupal.
I'm not exactly sure that if I change a file in there, it will automatically be reflected.
I just wanted to show an example of how when you're doing development in web, typically this is the way
you would do it without having to stop and start the Compose every time. Down here, under postgres, we
have the environment variable and the Secret settings like before. We have the defined volumes, and you'll
see down at the bottom,
I actually have the file-based secret because when we're doing local development, we have to use the file-
based secret.
Things get a little interesting when I look at this prod, or test files. The way this is going
to work is, remember that the .override.yml automatically gets picked up by the Docker Compose
command line. In prod or test,
I'm going to have to specify them manually.
So for test, we're going to have to use the -f command.
If you remember from earlier sections, the -f is when we do a docker compose that we want to specify
a custom file. I'll show you that in a minute.
Then in production, since we're not going to actually have the Docker Compose command line on a production
server, what we're going to do here is we're actually going to use a docker compose config command.
The config command is actually going to do an output by squishing together, or combining, the output of
multiple config files.
So that will be really cool.
Real quick, the test file just has the drupal and the postgres.
Imagine if this was your Jenkins CI or Codeship CI solution, where I want it to build the image
every time I commit my code, and I want to call it this, and I want it to be on this port for testing
purposes. Then I'm going to use a fake password. But I don't need to define any of the volumes because
I'm not going to actually try to keep named volume data because again, it's just a CI platform.
As soon as it passes tests or fails tests, it'll get rid of everything.
Then in this scenario, you might see that I've actually got this sample data scenario where maybe
in your CI solution, you have simply databases sitting there that come from either a custom Git repository
or maybe they're an FTP download. Or something happens during the initialization of your CI where it actually
downloads a database file. And instead of us having to create our database every single time we do CI
testing, we would just mount this directory of sample data into where our postgres data is supposed to
be.
And that way, we could guarantee we had the same sample data every single time we do a CI test.
I'm not going to go into that any further. I just wanted to show that that might be how this file
for CI would be different.
Then in production, we have all of our normal production concerns. We're specifying volumes for our
specific data. We're specifying our secret. And notice down at the bottom, we have the external secret.
Because we're going to have put the secret in already via the command line like we did in the earlier
assignment.
The point here is that all three of these configs are different in some way, but they all relate to
the core config, or the base config, which just defines the two services and their images.
You can see here. Here's a reminder of what it looks like.
Let's exit this and run a couple of commands.
If I look in this directory, you'll see that I have the base file and then the three override files.
Again, remember, that the override.yml is the default.
If I do a docker compose up, what it will actually do here is use the docker-compose.yml first,
and then it will overlay the override.yml one on top. I want to put a -d in so we can
take a quick look after it started. I'm going to do a docker inspect on the drupal image.
And what I wanted to show you was in here, it's got all the mounts listed.
So we know that it took the override file because the override file was where we defined all of these
mounts.
So we know that it picked that up.
Obviously, if it didn't pick up the base one, it wouldn't even know what images to use so it would
actually be complaining to us and saying that the Compose file was incomplete.
That one worked.
Let's do a down real quick.
If we were going to actually do the command we needed for our CI solution, what we would have to
do on our CI solution was to make sure that Docker Compose was there, and installed, and available so that
we could do docker compose commands. Then we can specify the -f,
and then the order of the f's is the base file always needs to be first.
So docker compose yml, then docker compose test.
If we did this with an up at the end and a -d, and then I went and inspected that same drupal,
you'll notice that there's no bind mounts.
They're completely missing because in the test file, we didn't specify those.
We didn't actually need Drupal to save information because it was going to be thrown away at the end
of our CI run.
And then third, we have the production config.
The production config is going to be a little bit different.
I'm going to hit the Up Arrow, and then here I'm going to do the prod. Instead of an up command, what I want to do
here is a config.
If you just look at the help real fast for the config, it has only two options and neither one of
those are really relevant in this situation.
What we want to just do is just run config by itself. What it's going to actually do is look at both
files and push them together into a single Compose file equivalent.
So what we could do here is just run this command somewhere in our CI solution. Then have
it output to a file, maybe with you know, something like that. That output file would be the one we would
use officially in production to create or update our stack.
However, I want to throw in a little caveat here.
This is all relatively new stuff.
We know that Secrets and Swarm Stacks are relatively new.
They're only a couple of months old.
As of this recording.
So there's a couple of rough edges.
We just ran that config command, and you'll actually notice that the secrets weren't listed in there.
That's a bug currently.
I'm actually working with the Docker team to see if we can't squash that bug.
So by the time you read this, it may have already been fixed.
Make sure you inspect that output of the config line before you go
deploying in production.
Secondly, the Compose Extends option, which I did not discuss here, is another way to override these
Compose files where you actually use the override file and you actually define an extends section in
there.
It's a little bit more declarative, so it's easier to understand. I'll provide a link in the references
for this section. Just know that that Extends option doesn't yet work in Swarms stacks.
I didn't mention it here because it doesn't really give you the full app lifecycle that we were hoping
for, but I do expect them at some point to do something about that.
Like either add it into Swarm or create a better workflow. Because that's really the idea
we're trying to get to with all of these tools, is to have a complete and easy lifecycle from development
all the way through test, into production, with the same set of configurations, in the same set of images.
I hope this got you thinking about how you might make your apps this way, and how you might extend
your own Compose files for complex scenarios.
Because nothing puts a smile on my face faster with Docker than when I see someone run a one line command
to do something that previously took multiple scripts to execute.