00:00:10.480
All right, it looks like we might have roughly everybody here, so I'm going to go ahead and get started.
00:00:17.920
Welcome to A Gentle Introduction to Docker for Rubyists.
00:00:29.840
I've started learning Docker a little recently, and by recently, I mean a year or two ago. I just began teaching Docker to myself.
00:00:40.399
My experience with the official Docker documentation and the general information available online is that it was really hard for me to understand.
00:00:46.480
Does anybody else have that experience looking at the Docker docs? Yeah, it seems pretty common.
00:00:56.960
I found it really tough; it took me a long time to make heads or tails of anything with Docker. Sometimes when I would talk to others who were already proficient, they acted like it was easy.
00:01:10.400
That was really frustrating to me—it's like, am I dumb or something? Why is it so easy for them but super hard for me?
00:01:21.360
So, what I'm going to do today is go really slow and start at the beginning—what is Docker, the foundational concepts, and why do people use Docker?
00:01:36.159
My hope is that I can do a better job of explaining some things today than the official Docker documentation does and most of the material online.
00:01:49.040
Now, as for the format: One thing I want to say is that in the past, I've facilitated workshops like this for corporate clients. I would fly to their office, and there would be a team of 10 to 30 people.
00:02:06.560
This is a much larger group than I am used to, so we'll see how it goes. I think it'll go fine, but it is definitely different.
00:02:20.080
For those people watching the video later, I have low hopes that this will translate well. Apologies to those watching at home; it surely will not be the same, but we will do our best.
00:02:32.000
The way I'm going to conduct this workshop is highly interactive and exercise-based. I'll do an exercise myself and then turn it over to you to do the same exercise.
00:02:42.240
During the time you're doing the exercises, I'll come around the room to check on everybody periodically and ask, 'Am I going too fast, too slow, or just right?' Please help me remember to do those check-ins. Sometimes I forget, but they are really important.
00:03:01.360
Working in pairs or groups is strongly encouraged, so if you'd like to buddy up with the person next to you and work on one computer, I think that's great.
00:03:14.560
In the workshops I've done where participants pair up, everything goes much better. The process of verbalizing things with your partner—like saying, 'I didn't understand this step,' and then discussing it together—helps a lot, especially with a group this size where I can't provide individual attention.
00:03:35.360
Questions are encouraged. If you have a question, feel free to interrupt me, or you can raise your hand, and I'll call on you.
00:03:54.240
Here's the overview of what we're going to do today. By the way, it's not super important for me that we get through all of this.
00:04:01.680
What I don't want to do is rush through everything just to get through it because you're not going to retain anything if we do it that way.
00:04:20.080
So, we're going to go at an appropriate speed. If we finish everything, great; if we only get a third of the way through, that's fine.
00:04:30.000
The important thing is that we go slow enough for you to understand and retain some of what you learn.
00:04:39.360
With that in mind, we're going to talk first about what Docker is. We'll discuss the two use cases for Docker, concepts and terminology, do a Docker Hello World, dockerize a Sinatra application, and then add Docker Compose to the Sinatra app.
00:04:48.960
If you're not familiar with Docker Compose, we'll go over what that is, and then we'll add a PostgreSQL database to our application.
00:05:09.520
A little bit about me: I'm the host of the Code with Jason podcast. By chance, are there any listeners in the room? I'm just curious, and it looks like there are at least a couple.
00:05:21.920
I wrote a small eBook called 'Docker for Beginners' that came out recently, which was a product of putting together this workshop, and I've also written a book called 'The Complete Guide to Rails Testing.' I blog at codewithjason.com.
00:05:39.680
Now, what is Docker? Does anyone feel like they could explain what Docker is?
00:05:47.200
Do I have a volunteer to give me their version of what they think Docker is?
00:05:53.760
A small virtual machine. Okay, that's probably the most common answer. You could say it's somewhat like a VM; it's not exactly a VM, but it's similar.
00:06:08.080
However, I think that's kind of the wrong answer because it's the right answer but answers the wrong question. When people ask, 'What is Docker?' they're not really asking mechanically how it works.
00:06:25.040
So I believe a better way to answer the question is to talk about why people use it. What are the benefits of Docker?
00:06:33.760
Does anyone have an idea of why people use Docker? I'm going to ask lots of questions throughout the workshop.
00:06:41.360
Quick dependency setup?
00:06:45.760
Any other use cases for Docker?
00:06:54.880
Managing different versions of the same software? Okay.
00:07:02.560
Here's what I came to understand regarding the use cases for Docker. It took me a lot of studying to arrive at this, and for some reason, they don't just tell you in the beginning; there are two use cases.
00:07:11.759
One is to make it easier to install and run your development environment's dependencies.
00:07:21.840
I'll say that again because it's a little bit of a mouthful: Docker makes it easier to install and run your development environment dependencies.
00:07:29.040
We'll go a little deeper into what that means shortly, but that's one use case—the development environment.
00:07:39.680
The other use case is for a production environment. Similar idea: it makes it easier to install and run your production environment's dependencies.
00:07:47.360
The mechanics of the production environment are a little different than the development environment.
00:07:56.000
There’s some overlap, but they are two kind of distinct use cases. Today, we are focusing on the development environment use case.
00:08:03.520
We are going to completely ignore the production environment use case. The reason for ignoring that is, first of all, there's already a lot we are going to cover.
00:08:10.560
We simply can't cover that much in this session. Also, between the two, the development environment stuff is easier to work with and understand.
00:08:17.680
All right, so we're going to get into the exercises shortly, but just a bit more context before we get to those.
00:08:31.760
Does anyone know in Docker terminology what a host machine refers to? I see someone nodding. What does the host machine mean?
00:08:46.560
Yeah, the host is the machine that the container is running on. If I'm running Docker on my computer, the host machine is my actual laptop.
00:08:54.080
Now, images and containers are big concepts. This will take a little time to explain, but here's my attempt.
00:09:00.800
One of the use cases for Docker is to make it easy to install and run your development environment's dependencies. Where do containers come into this picture?
00:09:10.480
If I have an application and I've Dockerized my database, I've only Dockerized my database—why would I do that? It helps me with one dependency.
00:09:21.760
I don't have to manually install PostgreSQL or whatever database management system I need. I can have my Docker config file, and PostgreSQL will be running.
00:09:31.440
That happens through a container. I will have a PostgreSQL container running on my computer.
00:09:43.600
This allows me to avoid having PostgreSQL installed on the host machine. Instead, I just have PostgreSQL in the container. When I connect to the database, I'll specify like we would with anything else: the IP address, username, and password.
00:09:58.320
Instead of pointing at my actual host machine's localhost, we point the database connection config at the container.
00:10:04.640
PostgreSQL is running inside that container. We'll come back to containers.
00:10:12.320
I don't expect many of these concepts to sink in on the first pass. It will take revisiting these topics several times. Just like it took me, I had to read definitions over and over before they finally clicked.
00:10:25.920
These definitions have intertwined dependencies. You have to hear one term, then another, and bounce around a little before you can understand them all together.
00:10:39.040
Let's think again about that PostgreSQL container where I have PostgreSQL running. It's like a computer inside my computer that's running PostgreSQL. The way I get there is I have a PostgreSQL image.
00:10:52.000
The image is like the blueprint, and the container is like the house. The image has the instructions: 'Here's how you make a PostgreSQL container.' You don't actually run the image, you just have the image on your computer.
00:11:04.960
When you want to run that thing, what you get is a container. So again, the image is like the blueprint, and the container is like the house.
00:11:19.200
These concepts will be easier to grasp once we get into the exercises.
00:11:27.679
A Dockerfile is a script with instructions for building a container. You define how to create an image from it.
00:11:36.800
For example, if you wanted to make a custom PostgreSQL image, you would have lines in your Dockerfile that say something like 'apt-get install postgresql.' That's where the Dockerfile comes into the picture.
00:11:50.480
Lastly, let's talk about volumes. Containers are ephemeral; you start and stop containers, create and delete them—they don't last forever.
00:12:02.400
This creates a problem when it comes to storage. Returning to the PostgreSQL example: your PostgreSQL database needs a place to store its data.
00:12:12.960
If you just keep that data in the container, when you stop or delete that container, you lose the data. Therefore, we can't do it that way.
00:12:26.080
The solution is to store data on the host machine. We'll see the details later, but the idea is simple: we link the PostgreSQL container back to a specified location on the host machine.
00:12:40.640
We configure the container to say, 'Hey, don't store this data inside the container; instead, store it on the host machine.'
00:12:54.480
Would you agree that this has been a lot to digest so far?
00:13:01.440
Okay, would it be beneficial to skip ahead and get started with the exercises?
00:13:08.040
The first exercise will be a Docker Hello World. I’m glad that apparently like two people have Lisp installed on their computer.
00:13:19.760
I picked Lisp because I assumed most people wouldn’t have it installed.
00:13:26.720
Here's what I want to convey: to me, the magical thing about Docker is that you can run services without actually having them installed.
00:13:31.760
Right now, we're going to get a Lisp image, run it, and get a Lisp container. We'll write some Lisp inside that container, and when we're done, we can delete everything without any evidence left behind.
00:13:46.720
That’s pretty neat because, to give another example, I have a WordPress site because my blog is on WordPress, but I loathe WordPress. I don’t want to install PHP and MySQL.
00:14:00.720
Instead, I've Dockerized my WordPress website, so when I want to work on it, I just spin up the container. I don't have to have PHP or MySQL installed on my actual laptop.
00:14:11.840
The other benefit here is that when a new programmer starts at your organization, it usually takes way less time to set up the development environment.
00:14:23.760
So, let's do a little exercise. How long has it taken someone in this room to get your development environment set up? Raise your hand if it has taken at least an hour.
00:14:36.960
We've got hands everywhere. How long did it take, for example?
00:14:42.080
At least four hours? At least a day? Isn't that right?
00:14:46.000
Almost everybody still has their hand raised. How about at least two days? A week?
00:14:52.000
I'm surprised that many people still have their hands raised for over a day or two.
00:15:02.720
Imagine if instead that can be reduced to just 10 minutes, and not just 10 minutes, but a really easy ten minutes.
00:15:14.480
The magic of Docker is that it can dramatically simplify this process, and I aim to convey some of that magic to you.
00:15:27.200
So, I'll do this on my computer, then turn it over to you to do it on yours. First, we're going to add a Dockerfile.
00:15:34.800
At the root of the project, we create this Dockerfile. I'll explain what all three lines mean.
00:15:49.280
A Dockerfile is the instructions for creating an image. The first line, 'FROM ubuntu:20.04,' states the base image.
00:16:02.160
The next line indicates what to run in the image. We can use 'RUN apt update and apt install -y sbcl.' This means to install Lisp.
00:16:12.000
Now, the '-y' flag means 'don't prompt me'; we want the initial installations to occur automatically.
00:16:29.200
The default working directory is going to be '/user/src,' so we would need that to know where to find our files.
00:16:39.680
Next, let's check for the images we currently have on our computer.
00:16:50.000
I'll see what images do I have, and let's ensure we don't have a conflict.
00:17:02.000
I'll run docker image ls and look for one related to hello.
00:17:10.400
Now, let's build this image. The command is 'docker build -t hello .' This specifies the current directory, where the Dockerfile is located.
00:17:21.600
Let's see what it does. Now we are installing Lisp using the instructions from the Dockerfile.
00:17:31.600
While we wait, does anyone have any questions? If so, feel free to ask!
00:17:49.680
Oh, I see a hand! Can you repeat that? Someone asked about the images—are they themselves based on a base image?
00:18:00.480
Correct! You can consider images as being built on top of one another.
00:18:10.240
Now, the build has finished, so let's run it.
00:18:13.680
Let's use the command: 'docker run hello.' This will run our container.
00:18:20.960
Again, this is a bit more complex since we need to map the ports, so we have to do port mapping.
00:18:28.280
Now let's go to the browser and check if it works. I'm heading to 127.0.0.1:4567 to see if there's a response.
00:18:39.280
Oh, it works! We've successfully run a Lisp application without installing it on our computer.
00:18:52.960
Now I'll exit the container and delete the image using 'docker rmi -f hello.' So there you have it.
00:19:03.680
What I want you to take from this is that you can run software without having it natively installed on your machine.
00:19:12.720
It’s an efficient way to manage dependencies. Would anyone like to try the exercise now?
00:19:21.760
If you didn’t follow along in real time, let’s take some time to catch up.
00:19:30.000
Can the people starting the exercise now raise their hands so I can assist?
00:19:37.600
Okay. Since we have less time left, I think I'll summarize and provide some additional explanations.
00:19:47.680
I had planned for a second exercise, but due to time, we might not cover it.
00:19:56.000
What I’ll do now is take your questions and review some of the terms we went over or additional terms I skipped.
00:20:11.680
Let’s take a brief break and regroup.
00:20:20.720
The time remaining is likely insufficient for a full exercise.
00:20:26.800
I’ll begin with dockerizing a Sinatra application.
00:20:36.960
If you'd like to follow along, feel free to do so asynchronously.
00:20:44.640
Let's start by creating a directory for our Sinatra app.
00:20:52.720
We will call it hello.rb.
00:20:59.760
It's a simple setup that maps paths to methods.
00:21:09.040
We need our gem file to install the Sinatra gem.
00:21:16.680
And finally, we need a rack-up file for our Sinatra application.
00:21:24.000
Next, I’ll do the undockerized version of the app to show the structure.
00:21:36.480
So I’ll do a bundle install first to install Sinatra.
00:21:42.960
Let’s run it: ruby hello.rb. It should be listening on 127.0.0.1 port 4567.
00:21:49.680
Let’s check it in the browser. It works!
00:21:57.840
Now we're going to create a Dockerfile for this application.
00:22:04.560
The first line indicates the base image, while the second line sets our working directory.
00:22:12.200
Next, we’ll copy files into the specified directory.
00:22:18.560
Line five is crucial because we’ll run 'bundle install' to install necessary dependencies.
00:22:29.440
We need to expose port 4567 and define the command that will run the Sinatra application.
00:22:39.680
After we finish building the image for the Sinatra app, let’s check for any naming conflicts.
00:22:49.520
I’ll keep this simple; let’s run docker image ls and see what we have.
00:22:58.960
Now, let's build the Docker image. We'll call it 'sinatra_app' or something similar to avoid conflicts.
00:23:07.760
It may take a moment, and we will see the progress reported.
00:23:18.760
We can install Sinatra using Docker!
00:23:28.960
As we finish building, I would love to hear any questions or thoughts about this process.
00:23:40.000
Shall we try running the application in Docker once we finish building?
00:23:52.160
Like before, we would map the ports from the container to the host.
00:24:00.480
After running that command, we should see the Sinatra app available.
00:24:10.320
Seems to be working! Given that we can see it accessible in our browser.
00:24:26.640
Now that we tested our app, it’s time to summarize.
00:24:35.760
Overall, I hope you feel more comfortable working with Docker!
00:24:49.400
Feel free to reach out during the rest of the conference if you have any further questions!
00:25:00.480
Thank you all for being here today!