Deploy an App Across Accounts

Move your app into another AWS Account in this multiplayer project! ✌️

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 hands-on ✌️ multiplayer ✌️ project on cross-account deployments!

Looking for a project buddy?

The best way to find your project buddy is by sending this message in the community! ⬇️

Hey everyone! Anyone down to try NextWork's multiplayer project together? Just say "hi" in a reply and we can sort out a time to work on it together 😊

In this project, get ready to...

  • 🐳 Build a Docker container image for your custom app.
  • 📦 Store your image securely in Amazon ECR (Elastic Container Registry).
  • ☁️ Share container images with your project buddy and launch each other's apps!

💭 Why care about cross-account deployments?

In the real world, teams often manage multiple AWS accounts to stay organized and secure. Cross-account deployments make it easy to move applications or services between these accounts without over-sharing access. It’s such a practical way to keep teams working smoothly while maintaining tight security and control over who can access what.

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

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

Choose Your Player...

Since this is a multiplayer project, there are ✌️ two players ✌️ you can pick from.

The difficulty levels for each player are the exact same, but there's a slight tweak in the app that you'll be creating for each other.

Welcome, Player B!

Have the most fun, and don't forget that Player A is your project buddy in crime in this one. The more you share and discuss, the more you'll learn together!

Note

If you're EVER stuck - ask the NextWork community. Students like you are already asking questions about this project.

Before we start Step 1...

Before we get started, it's important that you know what we're trying to do today... and Player A too!

Build your Container Image

Let's start, Player B!

We'll create a simple web app and package it into a Docker image to kick things off.

This will be the image that Player A will run later on.

In this step, get ready to:

  • Create files for building a Docker image.
  • Build a Docker image locally.

Installing Docker

Do you buddy already have Docker installed?

No

  • 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 are containers? Why do they exist?

Containers solve a common problem that comes with running software on different computers and servers. When you move applications to a different computer or environment, it might not run or behave in the way it was supposed to. This is because every environment/operating system has its own unique setup and way of running things!

Containers package up applications and everything it needs to run in one single file. Now other developers/users can run this package instead of the application itself, and they don't need to worry about environment set up.

💡 So what does Docker do?

Now that you know how containers work, Docker helps you create, manage, and deploy these containers efficiently. You're installing Docker Desktop, an app that makes it easy to use Docker on your device. It's kind of like how the AWS Management Console makes it easy for you to use AWS services!

  • 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.
  • 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:

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.

MacOS/Linux

Look for Terminal.

Windows

Look for Command Prompt.

  • 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!

Yes

Great! Here are two things to check off:

  • Check in with Player A - do they also have Docker already? Do they need any help with getting it installed?
  • Open Docker Desktop.

Create Dockerfile

  • Create a new folder on your desktop called DockerECR. You can create DockerECR by running this command in your terminal:
cd ~/Desktop
mkdir DockerECR

Why am I creating DockerECR?

This will be your project directory, which means its the local folder for your container image's files.

  • Create a new file called Dockerfile inside DockerECR. You can do this in your terminal by running the command:

MacOS/Linux

cd ~/Desktop/DockerECR
touch Dockerfile

What do these commands do?

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

Windows

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

What is a Dockerfile?

A Dockerfile is a document with all the instructions for creating your container image.

Once Docker reads your Dockerfile, it can create a container image that contains all the files and software packages that your Dockerfile says it needs.

💡 What's a container image?

A container image is a template used to create containers. It contains the application code, libraries, dependencies, and other files needed to run the application.

You can make multiple, identical containers from the same image, and all of those containers will run the same way no matter where it's deployed (as long as there is a container platform e.g. Docker to run the container).

This is great for developers working in a team, like you and Player A! Everyone gets the same experience with an application, so you're less likely to have an app work only for some developers and not others. It's also a lot faster for new team members to get up to speed with running the applications they need for a project to work.

  • Open your 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/

What do these lines mean?

Your Dockerfile contains all the instructions for creating your custom container image:

  • The first line, FROM nginx:latest, means we’re starting with a pre-built container image called Nginx. It's kind of like we’re reusing a classic recipe (the Nginx image) and adding our own modifications (the rest of your Dockerfile) to customize it for our needs, instead of writing an entirely original recipe from scratch.
  • 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.

💡 What's Nginx?

Nginx (pronounced as "engine-x") is a web server, which means it serves web pages to people on the internet. When you type a URL in your browser, it's the web server that sends the right web pages to your browser so you can see it on your device.

In this project, we're using Nginx to serve our simple web application so Player A can see your custom webpage (which we're creating next) when they deploy your app.

  • Save your work by pressing Ctrl/Command + S on your keyboard.

Create index.html

Now that we have your Dockerfile ready, Docker can later read your Dockerfile and create a container image with those instructions. One of those instructions is to serve an index.html file you create... let's put together that file now.

  • Create a file named index.html in your project directory using this command:

MacOS/Linux

touch index.html

Windows

cd ~/Desktop/DockerECR
New-Item -Path . -Name "index.html" -ItemType "File"
  • Open your index.html file:
    • In your Desktop, open your DockerECR folder.
    • Right click on index.html.
    • Select Open With >
    • Select your text editor.
  • Add the following content to index.html:
<html>
  <head>
    <title>Hello [[PLAYERANAME="Player A"]]!</title>
  </head>
  <body>
    <h1>Hello from [[YOURNAME="your name"]] at NextWork!</h1>
    <h1>If you can see this, you've deployed my app... nice work!</h1>
    <h1>You've unlocked my secret code: [[SECRETCODE="secret code"]]</h1>
  </body>
</html>
  • Make sure to replace Player A with Player A's name, and your name with your name.
  • Here's a challenge for this project! Replace secret code with your favourite food. If you can't decide, enter your favourite movie or song instead.
  • 🚨 You CAN'T tell Player A what you've written as your secret code - they can only find out once they've deployed your app successfully!
  • Check: Have you replaced Player A, your name and secret code?

Tip

The more you customise your index.html now, the more fun deploying the web app will get for both you and Player A!

We'd recommend adding even more content to spice things up 🌶️

For example, you could add something like this between the <body> </body> tags in index.html!

<h1>Something I've learnt about you today is...</h1>
<h2>And here's a special image chosen by me:</h2>
<img src="[[IMAGEURL="insert image URL here"]]" alt="Custom Image" style="width:100%; max-width:300px;">

If you're sharing an image URL, make sure it's an image that you can find online and that you're using its public Image Address.

  • Save your work by pressing Ctrl/Command + S on your keyboard.
  • Check that your index.html doesn't have any errors. In your DockerECR folder, right click on your index.html file and select Open With -> your browser app (e.g. Google Chrome).

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.

Still stuck? Ask the NextWork community!

Nice work! The files for building your container image are all ready.

Build Your Container Image

What does "build" mean?

In software engineering, build means taking source code (in this case, that's your Dockerfile) and compiling or packaging it into something else (in this case, that's the container image).

💡 Wait, I thought I already built my container image?

Not quite! So far, you’ve created the Dockerfile, which is just a set of instructions that tell Docker how to build the image.

Think of the Dockerfile like a recipe - it lists everything your container needs, but the actual container image (the finished dish) still needs to be built from it. This step is where we run the commands to create the actual image!

  • In your local terminal, run the command to build your image and name it cross-account-docker-app
docker build -t nextwork/cross-account-docker-app .
  • As this command runs, you might get popups asking you to grant your terminal access to other apps. This is because your terminal needs access to the Docker daemon for your docker build commands to work!
  • Your terminal will show you status updates from Docker on how it's building your container image.

🙋‍♀️ Getting an error message in the terminal?

It happens! Here are a few troubleshooting tips...

Docker Daemon

If you're getting an error message about docker daemon, make sure you have Docker Desktop open, or try quitting and re-opening Docker Desktop.

Docker Desktop

Try opening Docker Desktop and checking for any notifications.

You might find that one of the notifications is an error!

Select Find out more and let Docker Desktop Repair those issues for you.

You should be good to run the same docker build command from here!

Ask the NextWork community

If you're still stuck, ask the NextWork community!

Once the build is complete - voilá! 🎉

You've successfully built a container image. This means you've created a custom template that can be used to spin up containers running your web app!

  • You can also verify your built image using Docker Desktop.
  • Head to your Docker Desktop dashboard.
  • Select Builds from the left hand navigation panel.
  • Ta da! The image you've built should show up at the top of the list.

Now, anyone with access to this image (like Player A!) can use it to launch identical containers, making sure your app runs consistently across different environments.

Log in to AWS with an IAM user

We're about to dive into AWS now, Player B!

Log in to your AWS account with 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.

Set up ECR

Phew, you're all logged in now Player B!

Since you've built your container image, let's create a place to store it.

We'll use the Amazon Elastic Container Registry (ECR), which is like a storage space for container images in the cloud. It'll make sure Player A (and anyone else using your image) is always getting the latest version, so you don't have to manually send it to everyone each time.

In this step, get ready to:

  • Create a space in Amazon ECR to store your container image.

Create an ECR Repository

  • In the AWS Console, head to Amazon ECR, which is called the Elastic Container Registry service.

What is ECR?

ECR stands for Elastic Container Registry. It's a fully managed container registry that makes it easy for you to store, manage, and deploy your container images.

💡 Why do people use container registries?

If teams were to share container images manually (e.g. by sharing files manually), it could become a mess pretty quickly - different versions would get lost, updates would be hard to track, and there’s a risk of using outdated or the wrong images.

Using a registry like ECR ensures that every team member has access to the right image version at the right time. You can also use the commands for getting the latest image in automated workflows (e.g. CI/CD pipelines).

For teams building open-source projects or public apps, public repositories (like Docker Hub) let anyone pull their images. Private registries, like the one we're creating with ECR, are great for only giving access to the right people.

  • Select Create at the ECR welcome page.

What is a repository in ECR?

If Amazon ECR is a big storage space for all your container images, think of a repository as a specific, dedicated folder for each image. You'll need to set up a repository before you send any images into ECR.

  • Enter nextwork/cross-account-docker-app for the Repository name.
  • For Image tag mutability, select Mutable.

What is Image Tag Mutability?

Image tag mutability decides whether you can update an image that's marked with a tag. This is quite an important setting because developers often use tags (e.g. 'latest') to mark out important images in their project.

  • Mutable tags let you push a new image with the same tag, which overwrites the previous one.
  • Immutable tags prevent this, so a tag always points to the same image. Tip: 'Immutable' means unchanging over time, or unable to be changed!

For this project, we're using mutable tags for flexibility. You'll see this in action later on!

  • Leave Encryption configuration at its default setting.

What is AES-256?

AES-256 is a strong encryption standard used by ECR to protect your container images at rest. Encryption helps to make sure your images are confidential and can't be accessed by unauthorized users.

  • Select Create.
  • Wooohoo! Your new repository is born.
  • Click into your repository.
  • Select View push commands.

What is a push command?

A push command in Amazon ECR is used to upload your Docker container images to an ECR repository.

  • The push command window automatically selects macOS/Linux for the command instructions.

Should I stay on this tab if I'm using a Windows computer?

Make sure to switch the tab to Windows if that's your local computer's OS.

  • Copy the first push command, which will connect your local computer's terminal to your AWS account.
  • Head back into your local terminal and run your first push command.
  • Hmmmm... your terminal might not like this command. Does the terminal output say command not found: aws?

Yes, I see the error

What does this response in the terminal mean?

This message means that your terminal doesn't understand AWS commands yet - when you ran the push command, it's like you were talking to your terminal in a language it doesn't know yet. To fix this, we need to install the AWS CLI so your terminal can recognize and run those commands.

I've got a different error

If you've run into an authentication error (e.g., IncompleteSignatureException, UnrecognizedClientException, InvalidClientTokenId, or AccessDenied), this means you'll need to set up your CLI credentials in the terminal. Instructions for this in the next step!

If the terminal returns another kind of error, ask the NextWork community!

No errors for me!

Nice! If the terminal is asking for an Access Key ID straight away, it means you already have AWS CLI installed and configured.

The next step will be a breeze for you 🙌

Set up the AWS CLI

Let's recap: As Player B, your game plan for today is to build your own container image, push it to Amazon ECR and then deploy Player A's image.

You and Player A are ready to push your images now, but you need to set up your AWS credentials in your terminal first. Otherwise, you can't run the push commands to send your images to the cloud.

AWS Command Line Interface (CLI) is a handy tool that lets you manage your AWS resources right from your terminal, making it super convenient for tasks like creating repositories, managing users, and deploying applications.

In this step, get ready to:

  • Install the AWS CLI.
  • Set up your AWS logins for AWS CLI.
  • Log in to AWS... through your terminal!

Did you run into the command not found: aws error in the previous step?

Yes!

Awesome, we'll go through AWS CLI setup step by step together.

Lots of learnings coming your way in this step... get excited! We'll start by figuring out how to install AWS CLI.

I had a different kind of error

Aha! If you had an authentication error, you'll just need to configure AWS CLI.

Hooray - you can skip the steps for installing AWS CLI!

First, let's make sure Player A also has CLI installed, or work together with them to get it installed on their device too.

When they're also ready, you can head into configuring AWS CLI by clicking here.

I had no errors!

Legend! If you see a Login succeeded message, that means you should have AWS CLI installed AND fully configured.

Just make sure the IAM user that the CLI is using has AmazonEC2ContainerRegistryFullAccess permission - it would automatically have this if the IAM user is an Admin user.

Before you move on, let's make sure Player A also has CLI installed - work together with them to get it installed and configured on their device too.

Then, when you're both ready, you can jump straight to 🏓 Step #5!

Install the AWS CLI

The instructions for installing AWS CLI are different depending on your computer's operating system, pick the one that works for you.

MacOS

Open your local terminal (called Terminal) and run:

curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
  • Your terminal might ask for your password. Enter your usual password for logging into your Mac and press Enter on your keyboard.
  • That's it, your terminal will start downloading AWS CLI straight away!

Windows

Open Command Prompt and run:

msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi
  • That's it, your terminal will start downloading AWS CLI straight away!

Linux

Open your terminal and run:

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
  • That's it, your terminal will start downloading AWS CLI straight away!

What is AWS CLI?

The AWS CLI (Command Line Interface) is a powerful tool that lets you manage your AWS services from your terminal. Instead of having to use the AWS Management Console, you can now run text commands from your local machine.

We installed AWS CLI because it'll help us push our container image from our local computer into Amazon ECR (i.e. store your image in a cloud environment).

  • Once you've installed AWS CLI, open your terminal and run:
aws --version

You should see a version number for AWS CLI, which confirms you've installed it perfectly 🤙

Don't see a version number?

No stress - you got this:

  1. Make sure you've run aws --version without any typos or extra spaces.
  2. Check out the AWS CLI installation page for your OS. Mac and Windows instructions offer a package you could install without needing the terminal.
  3. Still stuck? Ask the NextWork community!

Nice work! You've just installed AWS CLI.

  • Head back into your Amazon ECR console.
  • Copy the first command in your ECR push command window. Here we go again!
  • Paste the command in your terminal and press Enter to run it.

Did you get this error in your terminal?

An error occurred (IncompleteSignatureException) when calling the GetAuthorizationToken operation: Invalid key=value pair (missing equal-sign) in Authorization header (hashed with SHA-256 and encoded with Base64): 'IOnOqOmusTv9aO9U76gbJpA8GtBWbt4JZpnBNnqOmsw='.
Error: Cannot perform an interactive login from a non TTY device

What does this error say?

Dang, looks like you still can't complete that first push command yet!

This error typically points to an authentication issue when trying to push a Docker image to Amazon ECR. In our case, AWS is telling your terminal that you don't have the right AWS credentials to run this command.

💡 But I own this ECR repository, how could I not have the right credentials?

That's 100% true - you created the ECR repository using the AWS Management Console... but you're interacting with the AWS CLI now. The Management Console doesn't have a way to automatically pass your credentials to the CLI, so think of this as having to log in to AWS again.

  • That's okay - let's set up your credentials for AWS CLI.
  • Run aws configure in your terminal to log in.
  • The terminal is now asking for your Access Key ID.

What is an access key?

Think of an access key as a set of credentials specifically made for scripts and terminal programs-it's like the AWS CLI’s way of logging in.

Even though you use your Management Console login on your browser, the CLI doesn’t know about that. It needs its own way to authenticate you, and accepting an access key is one of the fastest ways to do it.

Friendly reminder: It might feel a long road to push your container image to ECR, but you and Player A have got this and you're almost there 💪

AWS CLI is also an incredibly powerful tool to learn, many engineers prefer it over the Management Console!

Create an IAM User

Why are we creating a new user? I'm already using an IAM Admin User!

Logging into the AWS CLI works by creating an IAM user first, and then passing that user’s credentials in the terminal.

Even if you already have an IAM Admin User, we're setting up a brand new user so we can restrict its permissions to what you need for this project. Even if an attacker gets access to your key, the damage is limited which keeps your AWS account more secure!

  • In the AWS Console, head to your IAM console.
  • Select Users from the left hand sidebar.
  • Select Create user.
  • Enter ECR-Access for the User name.
  • We can skip the checkbox for providing this user access to the Management Console - we'll only use the terminal!
  • Select Next.
  • Select Attach policies directly.
  • Search for and select the AmazonEC2ContainerRegistryFullAccess policy.

What does this policy do?

This policy gives the user full access to ECR, which will definitely let you push your container image to your repository.

  • Select Next.
  • In the final review page, select Create user.
  • Nice work! Select View user in the green success banner.
  • Select Create access key in your IAM user's summary panel.
  • Select Command Line Interface (CLI).

Wow, what are the other options about?

These options help AWS know how you'll use your access key. For example, Local code is for scripts running on your machine, and Application on AWS is for services like EC2 or Lambda wanting to access other AWS resources. Each choice tailors the permissions that are possible based on your use case!

  • Check the acknowledgement checkbox at the bottom of the page.

Why is there an acknowledgement checkbox?

AWS usually recommends using another service called IAM Identity Center instead of access keys for managing programmatic access (i.e. access over the terminal), because it’s newer and more secure. This is especially true for larger teams, where you might need to manage CLI access for multiple people.

💡 Why are we creating an IAM user instead?

It's much faster to set up an IAM user compared to AWS IAM Identity Center - that deserves a full project on its own!

Note that even though we're using a classic, more traditional way to provide access, we're still following good practice by setting up a new user with limited permissions. This means we're only granting access to the specific services we need the CLI for, which is a much more secure way to set things up compared to making an access key for your IAM Admin/root user.

  • Select Next.
  • For the description, enter a short description like this:
Created to get programmatic access to ECR. Using this user for the NextWork project on cross-account deployment.
  • Select Create access key.
  • Well done! Your access key is created, and AWS has set you up with an Access key and Secret access key.
  • 🚨 Select Download .csv file. This is extremely important - you can't see the Secret Access Key again once you leave this page, downloading the .csv file is how you can keep a backup of your credentials!

Uh oh, I've already left this page

Ah, classic! Don't worry, you'll just need to delete the key you've set up and create another one. Don't forget to stay on the page the second time round!

If you're stuck while deleting your access key, ask the NextWork community!

Configure the AWS CLI

  • Head back to your local terminal again - this time you have credentials handy to access AWS CLI. Nice!
    • If your previous terminal sessions has closed, run aws configure again.
  • Copy the Access Key ID from the IAM console, and paste it in your terminal.

Uh oh, I've already closed that tab...

It happens! In that case, open the ECR-Access_accessKeys.csv file in your Downloads folder. You would've downloaded this file as your backup for credentials!

  • Paste the access key ID into your terminal.
  • Copy the Secret Access Key from the IAM console.
  • Paste the secret access key into your terminal.
  • Enter your AWS region code (e.g., us-east-1).

Where do I find my AWS region code?

  • If you're not sure, head back into your AWS Management Console, and open a new tab to find ECR again. Double check that you can see the repository you created in the previous step.
  • Expand the Region dropdown on the top right corner.
  • Copy the AWS code for that region. For example, you'd copy us-east-1 instead of N. Virginia.
  • You can leave the output format blank and press Enter on your keyboard. The default format for the terminal responses from your AWS commands is JSON, and that works great.

Push Your Docker Image to the Cloud

Niceeee work Player B, you have your container image ready and CLI all set up.

Now you can build your Docker image and push it to your ECR repository!

This will make the image available for Player A to deploy it in the next step.

In this step, get ready to:

  • Connect your local computer with ECR.
  • Push your container image to ECR.

Authenticate Docker to ECR

  • Head back to your ECR console, and select View push commands again.
  • Copy the first command again - third time lucky!
  • Run this command in your local terminal.

What does this command do?

This command gives Docker access to your private Amazon ECR repository.

  • aws ecr get-login-password gets a temporary password from AWS.
  • docker login and --password-stdin uses that temporary password to log Docker into your ECR registry.

💡 Why authenticate Docker with ECR?

Just like you need to log in to AWS to access services, Docker also needs permission to do anything in your AWS account. You'd want to give Docker access to your private ECR repository so that Docker can push container images there!

  • Success!

Build and Tag Docker Image

  • Back in your ECR console, check out the second push command... look familiar? You've actually already run this command to build your Docker image back in Step #1!
  • We won't need to build our image again, so we don't need to run the second command. Skip it!
  • Copy the third push command.

What does this command do?

After the build is completed, this command tags your image so you can push the image to your repository. A tag is like a label for a specific version of your image.

latest is a commonly used tag to represent the most recent version. This way, if you make updates to your code, you can rebuild the image, tag it as latest, and any deployments that reference latest will always pull the most up-to-date version.

  • In your terminal, run the command.

I'm getting an error here

Does your error message say No such image?

No worries, simply run that second push command to build your container image again and try the third command right after!

This error message pops up if Docker can't find the image you've built in Step #1, which would happen in scenarios where the image wasn't saved correctly due to a system or configuration error.

If you're still stuck or have a different error, ask the NextWork community!

Push Your Image to ECR

  • Back in your ECR console, copy the fourth and last (😮‍💨) push command.
  • In your terminal, run the command. The output should look like:

What does this command do?

docker push uploads your local Docker image to a container registry - for us, that's ECR. Pushing your image makes your image available for others to pull and deploy.

🙋‍♀️ Ran into an error?

You got this! Let's try the second command in ECR's push command window so you can rebuild your image. Then, copy and run the fourth command to push your docker image.

If you're still stuck, ask the NextWork community!

  • Success!
  • Head back to your Amazon ECR console and select Close on the push commands window.
  • Refresh the page.
  • You should see your amazing image stored inside!

Hold up... why do I see three images? Didn't we only push one?

When you pushed your image, Docker actually sent three related pieces to ECR even though it felt like a single action.

  1. The first piece is a tiny “table of contents” called a manifest list (ECR labels it “Image Index”). It tells ECR the kind images that are available for different computer chip types.
  2. The other two lines are the images themselves, each built for a different kind of computer chip. One of them is built for amd64, which is a common Intel chip, and the other is arm64, which is the newer Apple-style chip. Because these two images share almost all of their internal files, ECR reports one of them as taking up zero extra space.

Pull and Run Player A's Container Image

Player B are you ready for the ultimate crossover?!

It's time to share your container image with Player A, and pull their container image too.

In this step, get ready to:

  • Pull Player A's container image.
  • Now let's authenticate to ECR again!
  • Ask Player A to share with you the first push command to their private repository.
  • Run that command in your terminal.
  • Awesome work! You should be able to log in succsesfully.

How did that work? How am I logged in?

This login process doesn't actually check whether you have access to specific images or repositories; it's just trying to authenticate your AWS credentials against ECR.

So when you saw a Login Success message, this means Player A's ECR is giving you validation that you can run ECR commands.

The real test of permissions comes when you try to push or pull specific images from the repository 👀

  • Next, it's time for the big reveal... pull Player A's container image from their repository!
  • Ask Player A for the URI of their latest container image. Get ready to give them your latest container image's URI too!
  • If you're not sure where to find this:
    • Head to your ECR repository's page.
    • Find the image marked with the tag latest at the top of the images list.
    • Select the Copy URI button next to the latest image.
  • Now that you've swapped container image URIs, make sure to have Player A's URI handy somewhere. You'll use it a few times in this project...
  • In your local terminal, run the Docker command for pulling someone else's image. Make sure to replace player-a-uri with their latest image's URI.
docker pull [[PLAYERAURI="player-a-uri"]]
  • Whoops! You might see an error...

What is this error about?

The error message in the terminal says indicates that Docker couldn't pull a Docker image from Amazon ECR. The specific error is a 403 Forbidden response, which usually points to an issue with permissions or access rights.

Aha! Since repositories with ECR are private by default, both you and Player A have set up private repositories that no one else can access until you give someone else specific permissions.

Friendly reminder: You're SO CLOSE 💪 Just one last step to go!

Resolve Permission Issues

Player B, we've got a problem – your AWS account can't access Player A's private ECR repository yet.

Let's fix that!

In this step, get ready to:

  • Fix some permission settings in ECR.
  • Pull and run Player A's container image again.
  • See Player A's application live!

Update ECR Repository Policy

  • Switch tabs back to your AWS Managemnt Console.
  • Head to your ECR console in a new tab.
  • Select the Repositories tab.
  • Select the circle button next to your repository, and select the Actions dropdown.
  • Select the Permissions option.

What does the Permissions tab do?

The Permissions tab in ECR lets you control who can access your repository and what they can do with it. You can grant access to specific AWS accounts, IAM users, or IAM roles.

In our case, Player A is using their new IAM User ECR-Access to use AWS CLI, so we should be granting ECR-Acess the permission to access your repository

  • Select Edit policy JSON.
  • Add this policy to your JSON policy editor.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "[[PLAYERAARN="player-a-ARN"]]"
      },
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:GetDownloadUrlForLayer"
      ]
    }
  ]
}
  • ✋ WAIT
  • Before you save the policy, make sure to replace player-a-ARN with the ARN of Player A's ECR-Access user.
  • Player A is going to need your user's ARN too!

Do you think you know the steps for sharing your IAM user's ARN?

I can do this on my own!

Nice! Give it a go and send that ARN to Player A.

Uhhh, can you show me how?

  • Head to your AWS IAM console, and select Users from the left hand sidebar.
  • Select ECR-Access.
  • Find the user's ARN at the top Summary panel and copy it.
  • All done! Send that ARN to Player A.
  • Once you've entered Player A's ARN in your policy, select Save on the policy window.
  • Alrighty, let's give running Player A's container image another go.
  • Back in your local terminal, press the up arrow (↑) on your keyboard at the start of your terminal's new line to repeat the previous command. Run the command to pull Player A's container image again.
docker pull [[PLAYERAURI="player-a-uri"]]
  • Woohooo! You should be able to pull Player A's container image now.

How did it go - could you pull Player A's container image?

Yay! I ran into no errors

Great! You've successfully pulled Player A's container image. You can now move on to the next step.

I'm still getting an error message!

You might run into this error: no matching manifest for linux/amd64 in the manifest list entries.

Why did I get this error?

Any chance either you or Player A is using a Mac Apple chip e.g. M1, M2, M3 or M4; while the other person is using a Windows/Linux/Intel chip computer? This error pops up when you and Player A are using different architecture types!

💡 Extra for Experts: What is architecture and why does it matter?

The architecture (like amd64 or arm64) is a part of a computer's underlying hardware setup, particularly how it processes software instructions.

amd64 covers most computers, servers, and EC2 instances, while arm64 is used by newer Macs (with Apple Silicon) and any virtual servers that have ARM as their CPU.

While containers can bundle everything an application needs to run, they cannot change a computer's underlying hardware architecture. This means that containers built for one type of architecture (like amd64) won’t work on another (like arm64) unless it’s designed to support both.

Solving this error is easy - first you have to rebuild your container images using this special command below, and then pull each other's images again.

  • Back in your local terminal, rebuild and push your container image using a different command.
docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 -t [[CONTAINERIMAGEID="latest-image-id"]] 
--push .
  • Make sure to replace the placeholder for latest-image-id with the URI of your latest image!

Extra for Experts: What do the new build commands do?

You might notice that we used a simpler build command back in Step #1 - docker build -t nextwork/cross-account-docker-app . That first command builds your image on the same architecture as your own local computer.

Now that your container will be run by Player A, who's using a device with a different architecture, docker buildx create --use activates a more advanced Docker builder that builds container images compatible with both amd64 and arm64 architecture types.

  • Now try pulling each other's container images again using the command:
docker pull [[PLAYERAURI="player-a-uri"]]

I'm still stuck!

You got this! If you're still stuck, please ask the NextWork community!

  • Your terminal should show you a few updates as it pulls A's container image into your local computer.

You could confirm you've got your new image in two ways...

In the Terminal

  • Try running docker images in your local terminal.
  • You should be able to see the Docker image you've just pulled!

In Docker Desktop

  • Open the Images tab in your Docker Desktop dashboard.
  • You should be able to see the Docker image you've just pulled!
  • Now that you have Player A's container image with you, run this command in the terminal to run a container with this image:
docker run -d -p 80:80 [[PLAYERAURI="player-a-uri"]]

What does this command do?

We're asking Docker to run Player A's image as a container in the background (-d), making it accessible through port 80 on your local machine (-p 80:80).

🙋‍♀️ Seeing any errors with this command?

If your terminal says that it can't run this commamnd because your port 80 is already taken, you could also try other ports. For example, replace 80:80 with 8080:80 or 8081:80

If you're still stuck, ask the NextWork community!

  • Drumroll please 🥁 Now it's time to see Player A's application live!
  • Open a new browser tab and run localhost

Extra for Experts: How did I end up seeing Player A's web app?

Typing localhost in your browser means you want to connect to the server software running on your own local machine.

Since you've mapped port 80 of your machine to port 80 in the container that's running (this happened when you ran -p 80:80 nginx earlier in this step), the server software that localhost is connected to is the web server (Nginx) inside the container. That's why you end up seeing Player A's webapp!

🙋‍♀️ Don't see anything in localhost?

If you've mapped your container's port 80 to a different port in your local terminal, make sure to update localhost to use the updated port.

For example, if you ran your buddy's image with port 8080:80 instead, make sure to type in localhost:8080 in your browser.

If you're still stuck, ask the NextWork community!

Secret mission

Welcome to your 🤫 exclusive 🤫 secret mission!

Your mission, should you choose to accept it, is to deploy Player A's Docker image with Elastic Beanstalk, an AWS service for deploying and managing web apps.

💎 In this secret mission, get ready to:

  • Create a new Elastic Beanstalk application.
  • Write instructions on how Elastic Beanstalk should run Player A's container image.
  • See Player A's application live!
  • Showcase your secret mission in your project documentation.

Deploy Player A's app on Elastic Beanstalk

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!

Do you think you can delete the resources you've created today?

Yep, all done.

  • Your ECR repository
  • Your IAM user
  • Your Docker resources

I know, but also, I don't...

If you're feeling stuck (we've all been there!), here's a little guide:

  • Delete ECR Repository
  • In the AWS Console, navigate to your ECR console.
  • Select your repository.
  • Select Delete.
  • Select Delete again to confirm your deletion.
  • Delete IAM User
  • In the AWS Console, head to your IAM console.
  • Select Users in the sidebar.
  • Select the ECR-Access user.
  • Select Deactivate access key.
  • Select Delete.
  • In the delete panel, enter ECR-Access to confirm the deletion.
  • In your local computer, head to your Downloads folder.
  • Delete your .csv file containing your user's Access Keys too.
  • Delete Docker resources
  • Open your Docker Desktop dashboard.
  • Select the Containers tab on the left hand side.
  • Select the checkbox at the top of your containers list, select Delete and select Delete forever.
  • Select the Images tab on the left hand side.
  • Delete your images.
  • Select the Builds tab on the left hand side.
  • Delete your builds.

Nice Work!

Nice Work!

Is that a ✌️ pair ✌️ project COMPLETE?!

Wow, awesome work to the both of you - that's a power duo in the making.

Today you've learned how to:

  • 🔨 Build a custom Docker image: You created your own custom container image, which you built using Docker.
  • 🗃️ Store your image in Amazon ECR: You stored your Docker image in Amazon ECR, preparing it for Player B to pull and deploy.
  • 🔒 Configure IAM roles for cross-account access: You set up IAM policies to let Player B pull the image from your private ECR repository.
  • ☁️ Launch Player B's image in localhost: You also used ECR to run Player B’s Docker image, making the application available on your localhost.

Ready to quiz yourself? You got this! 💪

It's amazing that all these learnings are packed in one project. If you're keen to level up in deploying and managing containers, check out our Kubernetes series!

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!