Joannah Nanjekye

Ruby in containers

Ruby in containers

by Joannah Nanjekye

In her presentation at EuRuKo 2018, Joannah Nanjekye discusses the integration of containers in Ruby application deployment, emphasizing their advantages and best practices. Containers are popular not only due to trendiness but because they enhance application deployment, portability, and scaling capabilities. Joannah outlines the evolution from physical machines to virtual machines and finally to containers, highlighting the need for efficient resource utilization.

She elaborates on how containers work as storage for application processes, allowing developers to abstract applications from their operational environments. She primarily focuses on Docker, a popular container engine, while acknowledging the relevance of virtual machines for certain use cases.

Key Points Discussed:
- Definition of Containers: Containers package applications separately from the operating system to enable faster and more efficient deployment.
- Benefits of Containers: Containers boost reliability in deployments, increase productivity, and facilitate application scaling.
- Containerization Process: Nanjekye outlines a simple three-step process to containerize a Ruby application: creating a Dockerfile, building an image, and then running a container.
- Selecting Base Images: She advises the use of lightweight base images, like Ruby Alpine, to reduce container size and improve performance, further discussing how smaller images can lead to quicker boot times and fewer security vulnerabilities.
- Performance and Security Considerations: Emphasizing the importance of efficient container operations, she suggests minimizing installed packages and cleaning up after installations.
- Testing Containers: Joannah concludes by advocating for the importance of testing containers, parallel to code testing, to ensure their reliability within a development pipeline.

Overall, Nanjekye's presentation serves as a practical guide for Ruby developers to leverage containers effectively and to ensure that applications are scalable, secure, and efficient.

00:00:04 Thank you.
00:00:06 Chris, a couple of things were probably sticking to the end time of the lunch.
00:00:10 But probably not to the beginning time of lunch, so I will be cut, but it will look like it's not cut, I guess.
00:00:14 All right, I want to repeat that my DMs are open. If you have anything to say to the crowd, you can say it through me.
00:00:24 I have heard from some people that they didn't like my singing earlier. I take feedback really seriously, so I will not be singing anymore. Oh, this is really nice!
00:00:38 Okay, announcing our new speaker. She is a Rails Girls organizer, a Ruby friend, and an open-source enthusiast from Uganda.
00:00:52 She is the author of a book on Python 2 and 3 compatibility. She came out of the Rails Girls Summer of Code program in 2016 and now works at Outreach.
00:01:10 Today, she will tell us about the magic of containers and how we can all deploy our Ruby applications a lot better.
00:01:20 So please welcome Joanna!
00:01:30 Thank you very much!
00:01:35 As she said, my name is Joannah. I want to introduce myself, but I would just say that I'm a friend of the Ruby community.
00:01:39 I learned to program from a Rails Girls meetup, and that was my first language.
00:01:45 So I love being here today. We will talk about containers in the context of Ruby.
00:01:57 Containers are hot, but we're not just talking about them because they are trendy.
00:02:01 We talk about them because of the benefits they provide for our applications.
00:02:07 So we'll discuss the why, the what, and the best practices for using containers properly.
00:02:12 Let's start with what containers are. How do we use them in Ruby applications? I'm sorry for the people who are already experts.
00:02:20 We will go through a little background for those who do not yet know, and then I'll emphasize how we create small images.
00:02:26 It's important to work with small images in good practices with containers.
00:02:32 I'll also provide hints on how to ensure we have testable containers. Just to take you back a bit.
00:02:46 When we think about deploying Ruby applications, we usually have three things in mind.
00:02:53 We might be thinking about a physical machine, a virtual machine, or, in this era, containers.
00:02:57 Let's review: there was a time when deploying applications was literally an event, a ceremony.
00:03:06 We basically deployed applications on a machine where we had ensured that one application was running on a physical host.
00:03:19 We wanted to ensure that nothing went wrong because it was an event, and we aimed for stability.
00:03:26 If we had a good deployment, we wanted to make sure that nothing broke afterward.
00:03:36 Regardless of how big your machine was or how many features the host had, it ran only one application.
00:03:41 This was not good for the expensive computing resources we had only on one machine.
00:03:48 We needed a way to have multiple applications running on the same physical resources, maximizing utilization.
00:04:01 Eventually, we adopted virtual machines, allowing us to use the same hardware to run multiple applications.
00:04:07 With virtual machines, we were able to separate applications with guest operating systems.
00:04:17 We effectively virtualized the hardware, utilizing all our resources, which was a great improvement.
00:04:25 However, the downside was that virtual machines took a long time to boot up.
00:04:32 We needed a faster way to boot our applications.
00:04:35 So the solution was containers. What are containers?
00:04:45 In software development, containers serve as storage for application processes, packaging them logically.
00:04:58 This allows us to abstract applications from the environments in which they run.
00:05:06 In the container world, we virtualize the operating system, running our applications on top of a container engine.
00:05:14 There are many container engines available, but I will primarily talk about Docker.
00:05:23 Someone once told me that it's not a good idea to finish a technical talk without mentioning Kubernetes.
00:05:30 I do not want to give the impression that containers will solve every problem.
00:05:39 There is still a place for virtual machines, as they play their role well.
00:05:46 With virtual machines, we are virtualizing the hardware, running a guest OS on top of the host OS.
00:05:55 With a container, we operate without needing a guest operating system.
00:06:00 Containers allow us to boot our applications faster than virtual machines, which is crucial.
00:06:09 The only downside is that it can take a minute to start a container, but that is still faster.
00:06:16 There are three big benefits that come with using containers.
00:06:22 First, deployment used to be a ceremony due to reliability demands in production.
00:06:29 Calculating reliability in production is important since software needs to move across environments.
00:06:36 Additionally, containers provide us with the ingredients we need for scaling applications.
00:06:42 With microservices in containers, we can scale efficiently.
00:06:48 Let's talk about why we need to use containers.
00:06:52 Kelsey Hightower has shared various reasons, and I share his view that containers are packaging concepts.
00:07:00 Think of them as a ticket to modern platforms, such as Kubernetes.
00:07:09 By using containers, we can better manage and scale our applications.
00:07:13 Now let’s explore how we can containerize a Ruby application in three steps.
00:07:24 First, you create a Dockerfile with instructions on how to create your container.
00:07:32 The Dockerfile will specify how to execute your application and its various dependencies.
00:07:41 From this Dockerfile, an image is created that serves as a template for generating instances of your application.
00:07:50 Containers are specific instances created from images built using the Dockerfile.
00:07:55 This is a very simple three-step process you can follow.
00:08:01 You can always find additional details about creating a Dockerfile from numerous resources online.
00:08:10 For example, here’s a Hello World Sinatra application printing hello world and its respective gem file.
00:08:17 To start, create a Dockerfile, where you specify commands, including the base image.
00:08:28 In this case, we are using Ruby 2.3 Slim as our base image.
00:08:38 You could also use different operating systems like Ubuntu as your base image.
00:08:46 However, you may need to install additional dependencies later.
00:08:55 There are many other commands you can include in the Dockerfile.
00:09:02 However, that's not the focus of today; there’s great information available on Docker's website.
00:09:07 In the Dockerfile, you're specifying instructions on how to handle your application.
00:09:12 After creating the Dockerfile, you'll build an image from it and then run your container.
00:09:21 Essentially, you only need to install the Docker client to run both commands.
00:09:31 In summary, containers are essentially packaging solutions for applications.
00:09:41 They provide portability, increase productivity, and allow us to scale quickly.
00:09:47 To create a container for a Ruby application, create a Dockerfile, specify your instructions, and build the image.
00:09:55 Then, you can start your container. That's a summary of how to containerize a Ruby application.
00:10:05 Now, you could actually be doing this right now if you already had Docker set up. However, there’s more to consider.
00:10:21 It’s not just about creating a container; we need to address performance and security.
00:10:26 Performance is critical for efficiency, and security is essential to protect our applications.
00:10:33 To ensure our applications are performant and secure, we must focus on reducing the size of the resulting images.
00:10:42 By doing this, we will improve the performance of our applications.
00:10:48 A smaller image will reduce the time required to pull and push images to a registry.
00:10:56 Moreover, smaller images have a reduced surface area for potential security vulnerabilities.
00:11:06 When creating a small image, there are various techniques you can leverage.
00:11:18 For example, always start with a small base image and install only what you genuinely need.
00:11:27 This will prevent extra baggage that consumes unnecessary space.
00:11:34 To illustrate this, let’s take a look at a sample Dockerfile using the latest version of Ubuntu as the base image.
00:11:43 While this Dockerfile will work, its size is relatively large compared to alternatives.
00:11:51 For instance, the Ubuntu version may be around 187 megabytes, while Ruby Alpine weighs in at only 55 megabytes.
00:12:03 Choosing Alpine over standard Ruby images—863 megabytes—can significantly reduce your image size.
00:12:11 Using Linux Alpine could further drop you to approximately 5.249 megabytes.
00:12:19 From this analysis, we observe a clear pattern: the smaller the base image, the smaller your resulting container.
00:12:27 Thus, instead of Ubuntu, I would recommend using Ruby Alpine or Linux Alpine as your base image.
00:12:35 The advantages of boot time reductions and smaller vulnerabilities are well worth the effort.
00:12:41 Finally, using the RUN command in your Dockerfile means you can install necessary packages.
00:12:48 Chain your RUN commands to minimize the layers in your Docker image—this will help reduce the size.
00:12:56 Also, utilize the option -no-install-recommends to ensure you only install what's strictly necessary.
00:13:03 Additionally, always clean up unnecessary files after installation to reduce image size.
00:13:11 These are just a few effective tricks when working with containers.
00:13:19 If you want to learn more about creating smaller containers, there are many resources available.
00:13:26 For instance, a previous talk covered lots of techniques to build small containers.
00:13:31 Lastly, remember that containers must be tested just like the code we write.
00:13:37 Testing containers includes checking the commands within them, file existence, and metadata testing.
00:13:46 Using tools like Container Testing from Google can facilitate this process.
00:14:00 In conclusion, containers bring benefits in portability and scaling.
00:14:04 By creating smaller images, we improve our performance and security.
00:14:10 And just as we practice unit testing for code, containers ought to undergo testing as well.
00:14:18 Thank you!
00:14:23 These are the resources you can refer to.