Deploy an App with Docker

Let's learn how containers work using Docker and Elastic Beanstalk!

Introduction

This project has been archived

We're no longer updating this project - we recommend checking out our active projects instead!

If you've already completed this project, don't worry! Your documentation is still available for you to check out and share.

If you have any questions, leave a question in our Discord and we'll get back to you ASAP!

⚡️ 30 second Summary

Welcome to this compute project on containers and Elastic Beanstalk!

You'll get to create your own container (beginner friendly!) and run it using a platform called Docker 🐳

You'll also meet an awesome AWS service called AWS Elastic Beanstalk, which will help you deploy your containerized application in the cloud and make it available to the world!

💭 Why care about containers?

When developers create applications, they often use containers to package up their work and share it in a way that's easy for other people to run. Using containers has absolutely changed the game for making software fast and efficient, and it's also the reason why deploying software has become much simpler.

In this project, get ready to...

  • 🐳 Install and use Docker.
  • 🖼️ Build a custom container image.
  • 🚢 Run your containerized application locally.
  • ☁️ Deploy your containerized application to AWS Elastic Beanstalk, and access it live on the web.

Want a complete demo of how to do this project, from start to finish? Check out our 🎬 walkthrough with Natasha 🎬

If you're up for a bit of a challenge, quiz yourself on the key concepts up ahead in this project.

Before we start Step #1...

Before we get started, it's important that you know what we're trying to do today.

Install Docker

Welcome to Docker! Let's get to know this iconic tool by installing it and using it for the first time.

In this step, get ready to:

  • Install Docker Desktop.

Why are we installing Docker first? Docker is in the middle of our diagram

Docker is THE foundational tool today's project. The first element of our diagram, the source code, represents an app that we're about to build. Technically we could work on the source code first, but it'll actually be a lot easier to understand the source code if you install and use Docker first.

Installing Docker Desktop

  • Head over to the official Docker website.
  • Select Download Docker Desktop, and then select the version of Docker that matches your local computer's operating system.

How do I know which version of Docker I should download?

If you're unsure of which chip/settings option to pick for your device:

  • Mac: Select the Apple icon from the top left hand corner of your computer's menu bar. Select About this Mac, and note whether your Chip says Apple or Intel.
  • Windows: Click the Start button and search for System Information. Note whether your System Type says AMD64 or ARM64.
  • Linux: There's only one option for Linux, so you can pick that straight away!
  • Downloading Docker Desktop usually takes at least a few minutes. While we wait...

What is Docker Desktop?

Docker Desktop is a program that makes it easy to work with Docker, a tool for creating and managing containers (which we’ll talk about next). Engineers use Docker Desktop to build, test, and deploy applications right from their computers and use Docker in a user-friendly way.

💡 What are containers? Why do they exist?

Containers solve a common problem called the "it works on my machine" problem. Have you ever seen someone run code perfectly on their computer, but somehow get errors when you run the exact same thing on your own computer?

Software is not guaranteed to run and behave the way it's supposed to in every computer, because each machine comes with its own operating system, software versions, local resources and more.

Containers tackle this problem in two ways:

  1. Containers package up your application and everything it needs to run (i.e. dependencies) in one file. Now other developers can run this package instead of the application itself, which gets the application working much faster.
  2. Containers also let you run other develeopers' applications and software much faster, since a container comes with everything you need to get it working ASAP.

Containers are mostly used during the development phase of an app. For example, when a team is developing a complex web app, they might use containers to make sure eveyone in the team is working in exactly the same environment, even though they are on different machines. That's why containers are such a popular DevOps tool i.e. a tool for making software development and releases more efficient!

💡 So what does Docker do?

Now that you know how containers work, Docker helps you create, manage, and deploy these containers efficiently. You can think of Docker as a tool that helps you create the cargo and load them onto ships.

💡 Optional: If you want another explanation on containers...

Think of containers like those big shipping containers you see stacked on cargo ships. Each container has everything an app needs to run - its own code, libraries, and settings. You can load a bunch of these containers onto your computer, and they’ll all work smoothly together. That’s because containers package things up so neatly, the app just works wherever you put it. Moving apps around becomes a breeze!

  • Head to your computer's Downloads folder.
  • Install Docker Desktop:

MacOS

Double-click Docker.dmg to open the installer, then drag the Docker icon to the Applications folder.

Windows

Double-click Docker Desktop Installer.exe to run the installer. By default, Docker Desktop is installed at C:\Program Files\Docker\Docker

Linux

Install Docker Desktop using your specific Linux distribution.

  • Open Docker Desktop.
  • You might run into a confirmation popup that confirms whether you want to open this file. Select Open/Okay.
  • Welcome to Docker Desktop!
  • Docker Desktop will ask you to sign in right away - we don't need to do this. Select Skip.

Can I still use Docker without an account?

Yup! If you're just using Docker in your local computer (which is what we're doing), Docker will work just fine and your work will save locally. It's just like other software you download - some software will just work on your computer straight away, without you needing to create an account.

p.s if you ever want to save your Docker work in the cloud, that's when you'll definitely need to sign in.

  • You're now looking at your Docker Desktop dashboard.

Woahhhh... so what can I do in Docker Desktop?

Docker Desktop lets you manage everything about your containers. You can create new containers, adjust their settings, or monitor how they run.

💡 Extra for Experts: What are the tabs on the left hand side of this dashboard?

  • Ask Gordon is an AI assistant for Docker questions - handy if you need quick help or tips!
  • Containers is where you can start, stop, and manage your containers.
  • Images is where you manage your container templates. We'll cover this in the next step, don't worry if you don't get it now!
  • Volumes is where you can access data saved in your containers, even after you stop/restart them.
  • Builds is where you manage images you custom created or loaded into Docker.
  • Models is where you explore AI models that you can run and manage within Docker.
  • MCP Toolkit is like an app store for running AI tools (called MCP servers) using containers.
  • Docker Hub is Docker’s online repository where you can find and share Docker images (i.e. those container templates).
  • Docker Scout is a feature for analysing your Docker images for security issues.
  • Extensions is where you can integrate other tools into Docker, like container monitoring and security.

Let's try to verify that we've downloaded Docker successfully.

Why would I need to verify I've installed Docker? Isn't seeing Docker Desktop enough verification?

Think of Docker and Docker Desktop as two different things. Docker on its own is a tool for container management, while Docker Desktop is an app that makes using Docker more interactive and efficient. So downloading Docker Desktop doesn't necessarily mean you've installed Docker itself. It's best to check we've installed Docker itself!

  • Open the terminal in your local computer:

MacOS/Linux

Look for Terminal.

Windows

Look for Command Prompt.

What is a terminal?

A terminal is a place where you type out instructions for your computer, instead of using your mouse to click around. For example, instead of right-clicking to make a new folder, you can just type a command in the terminal and - voilà! - your computer does what you ask. It’s kind of like texting your operating system to get things done.

  • Run the following command:
docker --version
  • You should see your installed Docker version printed (it might take 30 seconds when it's your first time running a docker command)!

Seeing 'docker: command not found'?

  1. Restart both your Terminal and Docker Desktop and try running docker --version again.
  2. Open the Docker Terminal, which you can find at the bottom bar in your Docker Desktop. Run docker --version in your Docker Terminal. Do you see a version number now?
  1. If you do see a version number in Docker Terminal, this means you have Docker installed but it's not configured in your local computer correctly. Try hitting the notification bell and look for any issues that can be repaired.
  1. If you don't see a version number in Docker Terminal, looks like Docker hasn't been installed yet! Try installing Docker Desktop again.
  2. If you're still stuck, ask the NextWork community! It might be frustrating to not have Docker working right away, but we'll sort you out soon. If the Docker command works in Docker terminal, you can complete the rest of the project from there too!
  • Next, we'll verify that we've installed something called a Docker daemon. Look for the Docker icon (a ship 🚢) in your system tray, which is the bar at the top (for Mac) or bottom (for Windows) of your computer screen with small icons for running applications, WIFI, battery etc.
  • If you see the Docker icon there, it means the Docker daemon is running on your system.

What is the Docker daemon?

The Docker daemon is the engine that actually 🪄 does the thing 🪄 when you run Docker commands e.g. create a container.

In more technical terms, the Docker daemon is a background process that manages the Docker containers on your computer. It takes commands from the Docker client (i.e. commands you type into the terminal, or clicks you make through the Docker Desktop) and does the heavy lifting of building, running, and distributing your containers.

🙋‍♀️ I don't see the Docker daemon

If you're using a Mac and can't find the Docker 🐳 icon, try this: hold the Command key on your keyboard while moving an icon in your menu bar to the right, until it's more than halfway across your screen. This might reveal the Docker icon, which could have gotten cut off because of your camera. Simply rearranging can help the Docker icon appear, either before or after other icons. (Fun fact - hidden menu icons is a infamous issue called the MacBook notch 👀)

If you're using another operating system or you're still stuck, ask the NextWork community!

Run a Pre-Built Container Image

Wooohoo, now that we've installed Docker, let's use it to create a new container from an existing container image!

NOTE: We're not building our own application yet (that will happen in the next step), so think of this step as your training ground for learning how container images work before you build your own.

What's a container image?

A container image is a blueprint or template for making containers. It tells Docker exactly what to put inside each container - things like your app’s code, the libraries it needs, and any other required files.

You can create as many containers as you want from the same image, and they’ll all work the same way, no matter where you run them (as long as you have Docker or a similar tool). This consistency is a HUGE benefit for teams, since everyone can run the same app setup on their own computer without weird, unique issues popping up. We're less likely to see situations where an app only works for some members in the team and not for others. It also makes it much quicker for new team members to get started, since they can spin up the app in just a few steps.

In this step, get ready to:

  • Spin up a container from your local terminal.
  • See the container load a webpage in your browser!
  • Back in your terminal, run the following command:
docker run -d -p 80:80 nginx

What do these commands do?

docker run starts a new container. We're using a pre-existing container image called nginx and we're starting this container in detached mode (-d) so it runs in the background. Then, this -p 80:80 maps port 80 on your host machine to port 80 in the container, which means you'll be able to access the webpage that Nginx is running through your computer's web browser.

💡 What is Nginx?

Nginx (pronounced “engine-x”) is a web server, which is a program you use to run websites and web apps. If you want people to visit your site, you're going to need a web server to deliver your website's files to their browsers!

Engineers pick Nginx when they need to manage lots of visitors at once, making sure your site doesn’t slow down when traffic spikes. Nginx is also the web server of choice for containerized apps because it's lighter and uses less memory, compared to other options like Apache.

You should get this response in your terminal:

Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
... (download logs) ...
... Downloaded newer image for nginx:latest

Extra for Experts: Where did we get the Nginx image?

If you're wondering where the Nginx image is from, you can find nginx in Docker Hub (i.e. Docker's library of public container images) by clicking here.. Because Nginx is a pre-existing image, Docker knew where to find it in Docker Hub and downloaded it automatically.

💡 Extra for Experts: What is Docker Hub?

Docker Hub is a container registry, which means it's an online library where people can share and find Docker images.

psst... AWS also has its own container registry, called Amazon ECR (Elastic Container Registry).

  • Open your web browser and navigate to http://localhost. You should see the default Nginx welcome page.

Woah! How did I end up seeing this Nginx welcome page?

When you type localhost in your browser, the browser sends a tiny message (called a request) to your own computer asking, “Please show me a webpage.”

But how does your computer know which webpage to show? That’s where ports come in. Your computer has tens of thousands of ports, which you can think of as numbered channels that help direct requests to the correct server. Web browsers and web servers use port 80 by default.

  1. When you ran -p 80:80 nginx, this command connects port 80 on your computer to port 80 in your container (which is running Nginx).
  2. Then, when you type localhost into your browser, your browser sends a request to port 80 of your computer.
  3. Because of the connection you've set up, that traffic flows straight into port 80 in your container.
  4. Your container knows that port 80 requests should be automatically forwarded to its web server (i.e. Nginx), so Nginx receives the request and responds with its “Welcome” webpage.

💡 Extra for Experts:

Notice how we could run an Nginx server and open a webpage in seconds using containers. Doing the same with a virtual machine (like Amazon EC2) would take much longer - creating the EC2 instance takes more time because you'd need to install a full operating system and other software to create the web server. In general, containers lets you load and deploy applications faster than virtual machines.

Woohoo! 🎉 You've just taken your first steps into the world of containers! Get ready to build your own custom image in the next step. 🚀

Build your custom image

Now that you understand the basics of Docker, let's build our very own container image.

In this step, get ready to:

  • Write a set of instructions that tells Docker how to build your custom container image.
  • Get Docker to read your instructions and build the image.
  • In your local computer's Desktop, create a folder and name it Compute. You can do this in your terminal by running the following commands:
cd ~/Desktop
mkdir Compute

What do these commands do?

  • cd navigates your terminal to your computer's Desktop.
  • mkdir Compute creates a new folder named Compute. mkdir stands for 'make directory' i.e. create a new folder.
  • Create a new file in your Compute folder called Dockerfile (note that there is no file extension after the file name). You can do this in your terminal by running the command:

MacOS/Linux

cd ~/Desktop/Compute
touch Dockerfile

What do these commands do?

  • cd ~/Desktop/Compute navigates your terminal to your Compute folder.
  • touch Dockerfile creates an empty file called Dockerfile in the current directory i.e. the Compute folder.

Windows

cd ~/Desktop/Compute
New-Item -Path . -Name "Dockerfile" -ItemType "File" 

What is a Dockerfile?

A Dockerfile is a document with all the instructions for building your Docker image. Docker would read a Dockerfile to understand how to set up your application's environment and which software packages it should install.

  • You can confirm that you've created Dockerfile by clicking into your Compute folder on your Desktop.

Now let's fill in your Dockerfile.

  • Open the Dockerfile. You can use any text editor for this e.g. TextEdit on Mac or Notepad++ on Windows.
  • Add the following lines to your Dockerfile:
FROM nginx:latest
COPY index.html /usr/share/nginx/html/
EXPOSE 80

What do these lines mean?

The first line, FROM nginx:latest, means our image starts as a copy of the latest Nginx image, but we'll make a few modifications/additions to it to customise it for what we need. Think of it like you're copying an existing cheesecake recipe (the Nginx image) and adding your own twist to it (your modifications, specified in the Dockerfile)! The modified recipe creates a new dish, but luckily you didn't have to write the entire recipe from scratch.

Then, the next two lines in the Dockerfile customizes the base Nginx image:

  1. COPY index.html /usr/share/nginx/html/ replaces the default HTML file provided by Nginx with your own custom index.html file, so you're customizing the Nginx server to serve your own web content.
  2. EXPOSE 80 means you want the container to receive web traffic through port 80, which makes it easier for users and other services to reach your web app. Remember this, it's going to be important in the next step! 👀
  • Save your changes to Dockerfile by pressing Ctrl/Cmd + S on your keyboard.

Creating the web page for your container

Now that we have your Dockerfile ready, what is the web page that your Nginx container should serve? We'll put together a simple HTML file for this project.

  • Run these commands in your terminal to create a new file named index.html. This file should be in the same directory as your Dockerfile.
cd ~/Desktop/Compute
touch index.html

What is an HTML file?

The HTML file determines what your webpage will look like. It's a document that lays out your webpage's layout, text, images and links. When Nginx opens your HTML file, it will read the code inside and display it on the user's browser.

  • Head back into your Compute folder, and open your index.html file.
  • Add the following HTML content to your file.
    • Note: if double clicking on the file automatically opens index.html in your browser, make sure to right click on index.html instead and open it with your text editor.
    • Make sure you replace enter your name with your name.
<!doctype html>
<html>
  <head>
    <title>My Web App</title>
  </head>
  <body>
    <h1>Hello from [[YOURNAME="enter your name"]]'s custom Docker image!</h1>
  </body>
</html>

What does this index.html do?

This index.html will show visitors a heading that says "Hello from YOURNAME's custom Docker image!"

You'll see it in action soon 👀

  • Let's check that your index.html doesn't have any errors. In your Compute folder, right click on your index.html file and select Open With -> your browser app (e.g. Google Chrome).
  • You should see an HTML page showing the heading you wrote in your index.html file!

Seeing errors with your HTML file?

It happens! Especially if you're using TextEdit on a Mac, you might see this:

To solve this error, try opening your index.html file in another text editor (ideally a code editor like VS Code) and save your file again.

Thanks Michael for raising this potential error!

Still stuck? Ask the NextWork community!

Building the Image

Now, let's build the image!

  • Head back to your local terminal, make sure you're still in the Compute directory. Run pwd - does your terminal shows a directory that ends in Compute?

My directory doesn't show Compute

No worries! You can still get your terminal to head back into the Compute directory:

  • Check what's nearby - run ls to see which folders are in your current location.
  • Move up a level if needed - if you don't see Compute, use cd .. to go up one directory, then run ls again.
  • Enter the folder - once Compute appears in the listing, type cd Compute to switch into it.
  • Confirm: run pwd one more time; it should now end with /Compute.
  • Next, to build a new container image, run:
docker build -t my-web-app .

What does building an image mean?

Building an image means you're creating a Docker image using the instructions in a Dockerfile. Docker will then use the built image as the blueprint to create containers that run your application anywhere.

💡 What do these commands do?

-t my-web-app names your image my-web-app, and the . tells Docker to find the Dockerfile in the current directory i.e. the Compute folder.

Wow! What does the response from the terminal mean?

The terminal response shows the steps Docker took to build your image from the Dockerfile:

  • Loading build definition: Docker is loading the instructions in your Dockerfile to understand how to build the image.
  • [1/2] FROM docker.io...: Docker is processing the first line in your Dockerfile.
  • [2/2] COPY index.html...: Docker is processing the second line in your Dockerfile, which tells it to copy your index.html file into the container's file system.
  • Exporting to image: Docker is combining all the instructions applied to the image together, making it ready to run containers.

Run a container with your custom image

Image building done ✅

Next up is to run the container with the image we've built.

In this step, get ready to:

  • Run your custom container image, so you can see your webpage in action.
  • To run an image, use this command:
docker run -d -p 80:80 my-web-app

What does this command do?

Similar to the command we used before, we're asking Docker to run our my-web-app image as a container in the background (-d), making it accessible through port 80 on your local machine (-p 80:80).

  • Did you run into an error?
Error response from daemon: driver failed to remove network docker_default: Error during ipam/libnetwork driver backend operation: could not remove default bridge network: network docker_default id 6f79e5c38700 has active endpoints

Why did I run into this error?

This error comes up when there's already a container using port 80, so the new container you're creating can't access it.

Let's figure out who's taking up port 80 right now 🔎

  • You can find the container that's running in port 80 by visiting Docker Desktop again.
  • There should be a green container in your Containers page - that means a container is currently running.
  • Note that it says it's using the ports 80:80, which confirms why your new container can't use it.
  • Aha! the Image name for the running container says nginx. This is the container you created in 🖼️ Step #2 when you first ran docker run -d -p 80:80 nginx. Culprit found! 🧙‍♂️
  • You can then stop the container by selecting the square stop icon. The container icon should turn grey.
  • Another way to find the container is by running docker ps --filter "publish=80" in your local terminal. Your terminal should show you the id under CONTAINER ID.
  • You can then stop the container by running the following command:
docker stop [[CONTAINERID="CONTAINER-ID"]]
  • Don't forget to replace CONTAINER-ID with the actual ID of the other container.
  • Let's try to run the image again:
docker run -d -p 80:80 my-web-app
  • Sweet! No more errors this time.
  • Open your web browser and navigate to http://localhost again. If we've done everything correctly, then we should see the content of our index.html file.
  • Hooray!

Recap: Can you tell the difference between containers and container images?

In this example, the container image is the blueprint that tells Docker the application code, dependencies, libraries etc that should go into a container. The container is the actual software that's created from this image and running the web server displaying your index.html

Log in to AWS with your IAM user

Next up, it's time to deploy your containerized app to the cloud! For this project you'll need to log into AWS with your IAM user, not your root user.

In this step, get ready to:

  • Create / Log into your IAM user.

First things first... do you have an IAM user?

No

Oooo it's the start of a new era!

If you don't have an IAM user yet - here are the steps to create one (this takes less than 10 mins).

What is an IAM user? Why are we setting one up?

In AWS, a user is a person or a computer that can do things on the AWS cloud.

When you create an AWS account for the first time, the login you get is called the root user of the AWS account. AWS actually recommends to not use your root user for everyday tasks to protect it from security breaches.

You should create IAM users instead. If a root user is a master key to your AWS account, think of IAM users as key copies. IAM users have separate usernames and passwords to your root user, and you can set them to have limited access to your account's resources.

  • Head to your AWS Account as the root user.
  • Open the AWS IAM console.
  • From the left hand navigation panel, choose Users.
  • Choose Create user.
  • For the User name, name it:
[[YOURNAME="enter your name"]]-IAM-Admin
  • Make sure to select the checkbox next to Provide user access to the AWS Management Console - optional.‍

Note

This does not apply to all accounts, but if you're prompted with a pop up panel that says Are you providing access to a person?, choose I want to create an IAM user.‍

  • For the console password, choose Custom password.
  • Type in a password that you will be able to remember/access in the future.

Top tip

You will use this password for all future projects, so make sure to choose a secure one!

  • Deselect the checkbox for Users must create a new password at next sign-in - Recommended.
  • Choose Next.
  • In the permissions set up page, choose Attach policies directly.
  • From the list of Permissions policies, select AdministratorAccess.
  • Choose Next.
  • Choose Create user.
  • Voilà - you've just created your new user! Stay on this page.
  • Choose Download .csv file.
  • Copy the Console sign-in URL.
  • Now you're ready to start using your IAM user. 🏁
  • Log out of your root user's AWS Account.
  • Paste and go to your copied console sign-in URL.
  • Open your downloaded .csv file containing your user's access instructions.
  • Log in using your IAM user's username and password in the .csv file.
  • Once you're logged in, you're ready to use your IAM user for this project! Make sure to keep the login details safe - you'll need them for the entire 6 Day DevOps Challenge!

Yes

Nice! Log in to the AWS Management Console with your IAM Admin User.

Note

PLEASE make sure you log in to your IAM Admin User instead of the root user - it's truly best practice for account security.

Deploy your custom image to Elastic Beanstalk

In this step, we'll deploy your custom Docker image to AWS Elastic Beanstalk, a service that makes it easy for developers to deploy applications in the cloud.

This is the grand finale for the project - complete the application development process by making your app public on the internet!

In this step, get ready to:

  • Set up your application in Elastic Beanstalk.
  • Deploy your application and make it available to the world!

Creating an Elastic Beanstalk Application

  • Search for Elastic Beanstalk and click on the service.

What is Elastic Beanstalk?

AWS Elastic Beanstalk is a service that makes it easy to deploy cloud applications without worrying about the underlying infrastructure. You simply upload your code and Elastic Beanstalk handles everything needed to get it running, like setting up servers and managing scaling. This lets you focus on your application code without having to spend too much time on managing cloud infrastructure.

In more technical terms, Elastic Beanstalk handles things like:

  • Capacity provisioning
  • Load balancing
  • Auto-scaling
  • Application health monitoring

💡 How is Elastic Beanstalk related to containers and Docker?

Elastic Beanstalk is AWS’s way of running your Docker containers without the setup headaches. Build and test your app locally, wrap it into a Docker image, then hand that image to Elastic Beanstalk. It spins up the servers, launches your container, and keeps everything running for you - no extra configuration needed!

  • Click on Create Application in the Elastic Beanstalk homepage.

What is an Elastic Beanstalk application?

An Elastic Beanstalk application is like a folder that contains all the different versions of the same project/software you've deployed and the settings you've used to run them.

💡 I see lots of steps on the left hand side of the screen! What are these steps?

To set up your application, Elastic Beanstalk will take you through the steps for deploying the application and how you'd like to customise your deployment settings.

  • Welcome to the set up page for Elastic Beanstalk applications!

Note

Before we set up our Elastic Beanstalk application 🚨

In classic NextWork style, we're about go through and explain every step of the Elastic Beanstalk setup process together, but it's not required for you to understand every single setting we're about to see!

The key thing to note in this process is how simple it is to upload your containerized application to deploy it with Elastic Beanstalk.

In the Configure Environment page:

  • We'll leave the Environment tier as default.

What is an environment in Elastic Beanstalk?

An environment in Elastic Beanstalk is like the settings for the virtual machines that will run your application. When you configure your environment, you're deciding the instance type (the type of EC2 instance that will be running the container), scaling options (how many instances to run), network settings, and more.

💡 Virtual Machines? EC2? How does that relate to Elastic Beanstalk?

Elastic Beanstalk uses EC2 instances (i.e. virtual servers) under the hood to run your applications. Even though you're deploying a Docker container, it ultimately runs on an EC2 instance managed by Elastic Beanstalk.

  • Enter NextWork App as the application name.
  • We'll leave the Environment information section with the default values.
  • Under the Platform section, select Docker as your Platform.
  • The platform branch and version will be automatically selected for you too.

What does platform mean?

The platform is the technology that will open and run your application. We picked Docker because it's the best platform for deploying container images built with Docker.

  • Platform branch is the type of Docker we're using e.g. the default Docker running on 64bit Amazon Linux 2023 means we're using a type of Docker that's optimised to be used on an Amazon Linux 2023 operating system.
  • Platform version is the specific version of Docker we're using within that branch.
  • In the Application code section, select Upload your code.
  • Before we upload any code, head back to the Compute folder in your desktop and open up index.html with your text editor.
  • Find the line that says <h1>Hello from YOURNAME's custom Docker image!</h1>
  • Update index.html by adding a new line underneath the line you've found. For example:
<!doctype html>
<html>
  <head>
    <title>My Web App</title>
  </head>
  <body>
    <h1>Hello from [[YOURNAME="enter your name"]]'s custom Docker image!</h1>
    <h1>
      If I can see this, it means Elastic Beanstalk has deployed an image with my work.
    </h1>
  </body>
</html>
  • Save your updated file.
  • To deploy your code, Elastic Beanstalk needs your source code to be in a ZIP file. Let's create a ZIP file - in your Compute folder, multi-select both your Dockerfile and index.html, then compress them together.

Note

Tip: Lots of learners get this step wrong! Make sure you're NOT just selecting the root Compute folder and compressing the entire folder. Elastic Beanstalk would get confused if it opens your zip file and finds a subfolder inside, instead of the files themselves. Make sure you're selecting the two files and compressing at the file level instead.

  • Back to your Elastic Beanstalk setup page, enter Version One as the Version label.
  • Select Local file.
  • Under Upload application, select Choose file.
  • Select the ZIP file you created earlier. This uploads your application code to Elastic Beanstalk.
  • In the Presets section, choose Single instance (Free tier eligible).

Extra for Experts: What are Presets?

By selecting a preset, you are selecting a pre-defined way to set up Elastic Beanstalk recommended by AWS.

The Single instance preset creates a single EC2 instance, which is great for testing and is free tier eligible.

Other presets suit different kinds of scenarios and needs. For example, high availability comes with tools for handling any changes in traffic volumes quickly, which is great for applications that will be in production and used in the public.

  • Select Next at the bottom of the page.

In the Configure service access page:

  • Select Create role under the Service role heading.
  • This opens up a new tab with AWS IAM - once we create a new role on this tab, we can head back to our Elastic Beanstalk setup to use it.

What is a service role?

A service role is an AWS IAM role that lets Elastic Beanstalk permission to call other AWS services on your behalf.

💡 Why does Elastic Beanstalk need a service role?

One of the benefits of Elastic Beanstalk is that it can handle your application's cloud infrastructure for you, and it can only do that if it has the permission to use your AWS resources automatically e.g. creating a new EC2 instance. It also helps with automating tasks like scaling and health monitoring!

  • Keep the default Trusted entity type - it already picks AWS service, which is correct since we're creating this role for Elastic Beanstalk.
  • We can keep the default Use case too. It's already picked the correct service (Elastic Beanstalk) and use case (we're giving Elastic Beanstalk access to manage other AWS resources to create and manage an environment).
  • Select Next at the bottom of the page.
  • Now in the next page, we get to add the permissions linked to our service role!
  • AWS has already picked the best practice permission policies, based on the Service and Use Case we've picked.

Extra for Experts: What are the permission policies?

The permission policies are called AWSElasticBeanstalkEnhancedHealth and AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy.

Woah! Sound a little wordy? Luckily, what they do is a lot simpler than they might look...

  1. The first policy, AWSElasticBeanstalkEnhancedHealth, lets Elastic Beanstalk check how your application is doing (i.e. the 'health' of your app). It does this by giving Elastic Beanstalk access to read information from services like EC2, Auto Scaling, Elastic Load Balancing and SQS.
  2. The second policy, AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy, gives Beanstalk the authority to update your environment on your behalf. It does this by giving Elastic Beanstalk access to create, modify and tidy up resources during a platform upgrade, plus the right to pass other roles to the services it orchestrates.

Together, these two policies are the minimum that Beanstalk needs to monitor your environment and keep it up-to-date without asking you for additional permissions each time.

  • Select Next at the bottom of the page.
  • Use the default service role name, which should look like aws-elasticbeanstalk-service-role.
  • Now let's review your IAM role setup. Check if...
    • Step 1: Select trusted entities shows "elasticbeanstalk.amazonaws.com" as the trusted service.
    • Step 2: Add permissions uses AWSElasticBeanstalkEnhancedHealth and AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy.
    • Step 3: Add tags can be left empty. We'd use tags if we had lots of resources to keep and organize, but in this case, we're deleting all resources at the end of the project anyway - no need to keep tags!
  • Select Create role at the bottom of the page.
  • Nice! You should see that your role is all created. Well done!
  • Head back to your Elastic Beanstalk setup page.
  • Select the refresh button under the Service role heading.
  • Nice! You should be able to see your new role pop up as a dropdown option.
  • Under EC2 instance profile, choose Create Role again.
  • This time, do you think you can try create this role on your own?

Yes, I'll give it a go!

Yess go you! Once you reach the last setup page, make sure to name your role ecsInstanceRole

Ooo, actually can you give me the steps?

No worries, let's do it step by step together 🤛

  • In the first page, you might notice that AWS has again already picked the default values for us.
  • We'll leave those default values, which are exactly the same as the service role... except the last option.

Huh, which options are not the same?

In the Use case dropdown you’ll see Elastic Beanstalk - Compute instead of the Environment option we picked earlier. That’s because we’re creating an instance profile, not a general service role.

An instance profile is a special kind of IAM role that gets automatically applied to every EC2 instance that Elastic Beanstalk launches. These permissions let each EC2 instance talk to other AWS tools. In this case, our instances will need access to Amazon ECS, which is an AWS service that actually starts and stops Docker containers (more on this in our ECS project).

Think of Docker as the tool that builds a container, ECS as the manager that decides how many copies of that container should run, and Elastic Beanstalk as the environment that makes sure there are enough instances running your containerized app. By attaching the instance profile, we’re giving those EC2 instances the green light to ask ECS for more (or fewer) containers as network traffic goes up or down.

  • Select Next at the bottom of the page.
  • Next up, AWS has yet again picked the best practice permission policies for your EC2 instances 👌

Extra for Experts: What are the permission policies?

The first one, AWSElasticBeanstalkMulticontainerDocker, gives the instances permission to talk to Amazon ECS, the service that actually starts and stops your Docker containers. Without this, the containers wouldn’t launch, stop, or report their status back.

The second, AWSElasticBeanstalkWebTier, lets your instances save log files in S3 so you can debug any problems later.

The third, AWSElasticBeanstalkWorkerTier, is a different set of permissions designed to give an instance the permission to AWS services even if they were designated background tasks e.g. processing images or and generating reports.

  • Select Next at the bottom of the page.
  • For the Role name, let's enter ecsInstanceRole
  • Finally, it's time for the review!
    • In Step 1: Trust policy, the Service should show ec2.amazonaws.com
    • In Step 2: Add permissions, the policy summary should show AWSElasticBeanstalkMulticontainerDocker, AWSElasticBeanstalkWebTier, and AWSElasticBeanstalkWorkerTier.
  • At the bottom of the page, select Create role.
  • WOOO! That's your second role all done. Good work 👊
  • Head back to your Elastic Beanstalk setup page.
  • Select the refresh button under the EC2 instance profile heading.
  • Nice! You should be able to see your new role ecsInstanceRole pop up as a dropdown option.
  • At the bottom of the page, select Next.

Wait a second, are we skipping the EC2 key pair setting?

Yup! You'd typically use key pairs if you expect to log into these EC2 instances for troubleshooting or manual configurations. In our case, we won't need to log into our instances, we'll let Elastic Beanstalk handle all the server management for us.

In the Set up networking, database, and tags page:

  • Ignore the Virtual Private Cloud section - the default VPC looks good for this project!
  • Under Instance settings, check Enable for the Public IP address option.

What does activating a Public IP address do?

This makes your EC2 instances and your application accessible from the internet - exciting!

  • Skip the rest of the page, we don't need to set up a database for our webpage.
  • Select Next at the bottom of the page.

For the Configure instance traffic and scaling page:

  • Under the Instances section, for your Root volume type select General Purpose 3 (SSD).
  • For the Size select 10 GB.

Extra for Experts: What does root volume type mean?

The root volume is your EC2 instance's storage space, just like how your local computer would have it's own storage space for the operating system and files you keep locally.

General Purpose 3 (SSD) is Free Tier eligible and is fit for most applications.

Other root volume types are fit for special use cases, like Provisioned IOPS SSD for applications with high-performance databases, or Magnetic for data in long-term storage.

  • Under Instance metadata service (IMDS), make sure IMDSv1 is Disabled i.e. keep the Disabled checkbox checked.

Extra for Experts: What is Instance metadata service (IMDS)?

IMDS is a service that gives applications temporary credentials to your EC2 instances. For example, you can use IMDS to give your application the permission to access S3 to get data. Since our app won't need access to other AWS services, we won't need IMDS.

  • We don't need to configure anything else. Skip the security groups and Capacity sections.
  • Select Next.

Extra for Experts: What do these settings do?

Security groups control traffic, while Capacity controls the compute capacity of your environment and auto scaling settings to optimize the number of instances used.

In the Configure updates, monitoring, and logging page:

  • Under the Monitoring section, select Basic for your System.
  • 🚨 Make sure to select Basic for your System to keep your project free. 🚨

Extra for Experts: What are monitoring and health reporting?

Monitoring and health reporting tools give you performance and status updates on your Elastic Beanstalk application, so you can spot any performance issues before they affect your users.

  • Scroll to the Managed platform updates section.
  • Make sure to uncheck the Enable checkbox for the Managed updates option.

Extra for Experts: What do managed updates do?

Managed updates automatically update the software running your application in Elastic Beanstalk e.g. Docker. This makes sure your application stays secure and stable without needing manual updates.

We don't need managed updates since we aren't keeping this application for long (we're deleting our resources by the end of this project)!

  • Now in the Rolling updates and deployments section, accept the default All at once deployment policy.

Extra for Experts: What are application deployments?

Application deployments move a new version of your software into production on Elastic Beanstalk. This includes uploading your code, setting configuration options, and finally, replacing the old version with the new one on the live environment that users see.

There are two main types of deployments, also called deployment policies:

  • All at once updates all instances at the same time, resulting in a brief period of downtime.
  • Rolling updates instances gradually, which minimises downtime.
  • Leave all other options, including the Platform software section as default.

Extra for Experts: What is the platform software section?

Platform software is the software that runs the instances in your Elastic Beanstalk environment. For example, Elastic Beanstalk has set up Nginx as a proxy server for us by default, which means Nginx will handle sending incoming traffic to the EC2 instances running your application and pass responses back to the user.

  • Select Next at the bottom of the page.
  • For the final step, we'll just need to review our Elastic Beanstalk setup. This rounds up your selections across the last five pages.
  • Let's run a quick checklist and scavenger hunt. Is...
    • Application name NextWork App?
    • Application code a zip file?
    • EC2 instance profile set to ecsInstanceRole?
    • Public IP address set to true?
    • Root volume type set to gp3?
    • Environment type set to Single instance?
    • System set to basic?
    • Managed updates set to Disabled?
    • Deployment policy set to AllAtOnce?
  • Click Create.

This starts the environment creation and application deployment process. This process can take several minutes. While we wait...

Why does this process take several minutes? What's happening in the background?

We'd recommend continuing to refresh your page and check the latest updates in the Events page!

Elastic Beanstalk is provisioning your entire infrastructure from scratch - creating EC2 instances, setting up security groups, configuring load balancers, and deploying your application code. It's like building a small data center just for your app, which takes time to make sure everything is properly configured and secure.

  • Once your app is deployed, you'll see a green banner at the top of the page - environment launch success!

Ran into an error with your environment?

It can totally happen, try double checking whether you've ticked off everything in the final review checklist e.g. is your Root volume type accidentally set to gp2 instead of gp3?

If you're still stuck, ask the NextWork community! It might be frustrating to get the environment to launch successfully right away, but we'll sort you out soon.

  • Shall we see our environment in action? Click on the Domain link on the environment dashboard.

Wow! The Domain link takes you to a webpage showing you your updated HTML file. Nice work! tells us that Elastic Beanstalk has successfully deployed your ZIP file's contents as a container image.

Before deleting your resources today, you can even share the Domain link with someone else - ask them to open your webpage from their device!

Secret mission

Welcome to your 🤫 exclusive 🤫 secret mission!

Your mission, should you choose to accept it, is to deploy an app update with Elastic Beanstalk.

💎 In this secret mission, get ready to:

  • Make changes to your index.html file.
  • Deploy the new version of index.html using Elastic Beanstalk.
  • See your latest changes live!
  • Showcase your secret mission in your project documentation.

Deploy an App Update

Delete Your Resources

Delete Your Resources

Important

Make sure to delete all your resources when you’re done to avoid unexpected charges. Yup - if you don't delete all your resources, you might get charged!

Before you read the steps on deleting your resources, do you think you can challenge yourself to try delete everything in this project without any guidance?

Keeping track of your resources, and deleting them at the end, is absolutely a skill that will help you reduce waste in your account.

  • The Elastic Beanstalk environment
  • In the Elastic Beanstalk console, navigate to your NextWorkApp-env environment.
  • Select the Actions dropdown, and select Terminate environment.
  • Enter the name of your environment i.e. NextWorkApp-env.
  • Select Terminate.
  • This will delete all resources associated with your environment, including the EC2 instance.
  • Select Applications from your left hand sidebar.
  • Select NextWork App
  • Select the Actions dropdown, and select Delete application.
  • Enter NextWork App and select Delete.
  • Files in S3

Did you just say... S3?

When you uploaded code to Elastic Beanstalk, where do you think AWS would store your files? 🤔

Yup! AWS would automatically create an S3 bucket and store your .zip file there. Let's delete those so you don't incur any storage costs.

  • In your AWS Management Console, head to the S3 console.
  • Select General purpose buckets from the left hand sidebar.
  • Select the bucket that AWS automatically created for you. Its name should start with elasticbeanstalk
  • Select Empty, and type in permanently delete
  • Select Exit.
  • Select the bucket again, and this time select Delete.
  • Enter the name of the bucket and select Delete bucket.

I ran into an error deleting this bucket!

No stress! Let's work through a permissions error like this one together.

  • Select Cancel.
  • Click into your elasticbeanstalk bucket's name.
  • Select the Permissions tab.
  • At the Bucket policy section, select Delete at the right hand corner.
  • Type delete and select Delete.
  • Select Buckets from the left hand sidebar, and try deleting your bucket again.
  • Containers and container images

It doesn't cost any money to store containers in Docker, but it's best practice to remove resources that you won't need anymore.

  • Head back to the terminal in your local computer.
  • Run docker ps -a to list all containers (running and stopped).
  • Can you tell why there are two or three containers listed? Hint: you've deployed two containers in this project!
  • Identify the running container i.e. the container running the my-web-app image. You can tell it's still running as its status still says Up x hours, which means it's been running for that amount of time (and counting).
  • To stop your running container, run:
docker stop [[CONTAINERID="CONTAINER-ID"]]
docker rm [[CONTAINERID="CONTAINER-ID"]]
  • Don't forget to replace CONTAINER-ID with the actual ID of the running container.
  • Next, we'll remove the container images too.
  • Run docker images to list your local images.
  • To remove images, run:
docker rmi [[IMAGEID="IMAGE-ID"]]
  • Don't forget to replace IMAGE-ID with the ID of the image you're removing.
  • Check: Once you've deleted all containers and images, no results should show when you run docker ps -a and docker images again.

Nice Work

Nice Work

You've just conquered the world of containers and Elastic Beanstalk! Congrats, give yourself a pat on the back 😎

Today you've learned how to:

  • 🐳 Install and run Docker: You installed Docker on your local machine, which lets you create, manage, and run containers for your applications.
  • 🔨 Build a custom Docker image: You used a Dockerfile to define a Docker image that packages up your index.html file.
  • ☁️ Deploy your image to AWS Elastic Beanstalk: You uploaded your custom Docker image to AWS Elastic Beanstalk, which served your application in the cloud so you can access it from the internet!

Ready to quiz yourself? You got this! 💪

It's amazing that all these learnings are packed in one project. Great work and we'll see you in the next project on Docker and containers: Deploy an App Across Accounts

p.s. Does it say "Still tasks to complete!" at the bottom of the screen?

This means you still have screenshots left to upload, or questions left to answer!

  1. Press Ctrl+F (Windows) or Command+F (Mac) on your keyboard.
  2. Search for the text Return to later.
  3. Jump straight to your incomplete tasks!
  4. 🙋‍♀️ Still stuck? Ask the community!