Manually Deploy Docker to EC2

Build, publish, and manually deploy a versioned Docker image to Amazon EC2.

Introduction

30 Second Summary

Moving an application from your laptop to a public server can feel like a chain of hidden handoffs. When one link fails, the browser gives you little clue about where the problem lives.

In this project, you will manually deploy your existing bootcamp application to Amazon EC2 with Docker through Docker Hub. You will trace the full path from a local build to a browser-accessible cloud deployment.

What You'll Build

You will refresh a public URL and see the same bootcamp application you proved locally running from a versioned container on Amazon EC2.

By the end of this project, you'll have:

  • A locally tested Docker image that runs your real bootcamp application in the browser.
  • A published release whose exact version tag is visible in your private Docker Hub repository.
  • An end-to-end deployment you can demonstrate with the live page, the running image tag, and evidence of the blocked network path you fixed.
  • Secret Mission: Publish a second version with its own tag. Deploy it manually. Then roll back to the original tag.

Are there any prerequisites?

You need an application from your current TechWorld with Nana bootcamp work with a valid container build definition. You also need access to AWS and Docker Hub accounts.

Before We Start

Before any hands-on work, this checkpoint commits you to the existing bootcamp application you will deploy. Success means loading the application in your browser from a Docker container on Amazon EC2 while keeping its source layout plus container build definition unchanged.

Verify the Toolchain and Accounts

Your deployment path begins on Windows 11. It later reaches Amazon EC2.

An unchecked WSL2 connection can stop the project before cloud work begins. A disconnected Docker Desktop engine can cause the same block before AWS usage starts accruing.

In this step, get ready to:
  • Confirm the Windows-to-Ubuntu toolchain is ready.
  • Authenticate the workstation to Docker Hub.
  • Confirm the AWS account has a chosen Region plus known cost coverage.
Confirm Ubuntu uses WSL2

Windows reports the WSL version assigned to each Linux distribution. The PowerShell check must show Ubuntu on version 2.

The Windows and Ubuntu terminals look similar, so this check is easy to run in the wrong place. Start from PowerShell to inspect WSL from the Windows side.

  • Press the Windows key to open search.
  • Type PowerShell into search.
  • Press Enter to open PowerShell.

Before you run the check, do you expect Ubuntu to report WSL version 2?

  • Check the installed WSL distributions by running this command:
wsl.exe --list --verbose

What Does This Command Show?

  • The PowerShell check lists each installed WSL distribution.
  • The state shows whether each distribution is currently running.
  • The version column identifies the WSL generation used by each distribution.

You should see Ubuntu in the distribution list. Its version column should show 2.

Ubuntu Not on WSL2?

  • Follow Microsoft's WSL command guide to convert the Ubuntu distribution to WSL2.
  • Repeat the PowerShell check after the conversion finishes.
  • Ask for help using your non-sensitive WSL output: Help me understand why Ubuntu is not reporting WSL version 2.
Verify deployment commands in Ubuntu

Docker separates its command-line client from the engine that runs containers. Git tracks the application source.

OpenSSH provides the remote connection used later for EC2. These checks confirm that Ubuntu can reach every local deployment command.

  • Press the Windows key to open search.
  • Type Ubuntu into search.
  • Press Enter to open Ubuntu.

Before you run the checks, which commands do you expect to reach a service beyond the Ubuntu shell?

  • Check Docker engine access plus the supporting deployment commands by running:
docker version
docker info
git --version
ssh

What Do These Checks Prove?

  • The first Docker check confirms that Ubuntu can reach the command-line client plus the container engine.
  • The second Docker check displays system-wide engine information.
  • The Git check prints the installed version.
  • The ssh check prints its usage because no remote destination was supplied.

The Docker output should include a Client section. It should also include a Server section.

Git should print a version. The SSH command should print usage information.

✔️ All four checks pass

That confirms the local toolchain is ready. Ubuntu can reach Docker Desktop plus the commands required for the manual deployment.

ⓧ Docker has no Server section

A missing Server section means Ubuntu cannot reach the Docker Desktop engine.

  • Press the Windows key to open search.
  • Type Docker Desktop into search.
  • Press Enter to open Docker Desktop.
  • Select Settings.
  • Select Resources.
  • Select WSL Integration.
  • Enable integration for Ubuntu.
  • Apply the WSL integration change.

Docker Desktop now exposes its engine to Ubuntu.

  • Return to Ubuntu.
  • Repeat the two Docker checks from this substep.

The Docker output should now include both the Client section plus the Server section.

Is Git or SSH Unavailable?

  • Confirm that you ran the checks inside Ubuntu.
  • Restart Ubuntu through Windows search before repeating the affected check.
  • Ask for help using only the non-sensitive output: Help me diagnose the missing Git or SSH command in WSL2 Ubuntu.

Why Leave Jenkins Alone?

Your existing Jenkins container stays unchanged during this project. The manual deployment creates the baseline that Jenkins can automate in Part 2.

Authenticate accounts and record the baseline

Your existing accounts are the final prerequisites. Docker Hub supplies authentication for the registry handoff.

The AWS Management Console shows the Region plus account cost coverage that later EC2 choices depend on.

Keep Credentials Out of Your Notes

Authentication screens handle sensitive data. Your project notes only need successful outcomes plus non-sensitive configuration choices.

  • Return to the Ubuntu terminal from the previous substep.
  • Start Docker Hub's browser-based device flow by running this command:
docker login

What Happens During Login?

Docker Hub displays a temporary device code plus a browser sign-in route. The terminal waits while you approve the authentication in your browser.

  • Switch to the browser page opened by Docker.
  • Complete sign-in with your Docker Hub account.
  • Return to Ubuntu.

The terminal reports successful authentication. Docker Hub can now identify this workstation.

Does Docker Hub Authentication Fail?

  • Complete the browser flow using the same Docker Hub account that owns your repository allowance.
  • Repeat the login command from this substep after completing the browser flow.
  • Ask for help without sharing the device code: Help me diagnose my Docker Hub browser login.

Billing pages can feel high-stakes. This check only identifies whether your account has applicable Free Tier eligibility or credits before you create anything.

  • Open a new tab in the browser.
  • Go to the AWS Management Console.
  • Sign in to your AWS account.
  • Use the Region control in the console header to select one AWS Region for the entire project.
  • Record the Region in your project deployment notes as your selected AWS Region.
  • Use the console search to find the account page that shows Free Tier eligibility or credits.
  • Check the account's current Free Tier eligibility or credit status.
  • Record the result in your project deployment notes as your Free Tier or credit status.

Your console now has a chosen Region. Your notes now capture the account's current cost coverage.

  • Update the project deployment notes from earlier with this verified baseline:

Before you review the baseline, which missing result would stop the manual deployment first?

  • Confirm the notes still identify the selected bootcamp application.
  • Confirm the notes include the WSL2 plus local tool verification results.
  • Confirm the notes include the selected AWS Region plus account cost status.
  • Confirm the notes contain no passwords, tokens, device codes, or private keys.

You should see one safe deployment baseline covering the application, local toolchain, registry access, AWS Region, and cost status.

That is the setup risk handled: your workstation plus accounts are ready for the manual deployment path. Next, you will build a version-tagged image from your existing bootcamp application.

Build and Test the Image Locally

Your verified Docker toolchain can now package the bootcamp application you selected. This step turns its current source state into a versioned container image.

A cloud deployment should promote an image that already works locally. The local proof also exposes a limitation: Amazon EC2 cannot retrieve the image until you publish it through an image registry such as Docker Hub.

In this step, get ready to:
  • Identify the build context plus the values that define this release.
  • Build the application as an explicitly tagged image.
  • Run the image locally before removing the temporary container.
Identify the image inputs

A build context tells Docker which application files are available during the build. Your existing bootcamp workflow may also supply build options required by that application.

The container port can be easy to confuse with the host port. The container port belongs to the application inside Docker.

  • Return to your project deployment notes from earlier.
  • Record the existing application build context as <build-context>.
  • Record the existing build options as your existing build options.
  • Record the application's internal listening port as <container-port>.

What Makes This Release Identifiable?

The repository identifies the application image. The immutable version tag identifies the exact application state you tested.

The local container name only identifies the temporary test container. The host port gives your browser a route into that container.

  • Record your Docker Hub username as <docker-hub-username>.
  • Choose the image repository name as <repository>.
  • Choose an immutable original tag as <version-tag>.
  • Choose the temporary container name as <local-container-name>.
  • Choose an available local host port as <local-host-port>.
Build the versioned image

The image reference combines your Docker Hub username with the repository name. Its tag preserves the identity of the release that passes this local test.

  • Return to WSL Ubuntu from earlier.
  • Move to the directory used by your existing bootcamp build workflow.
  • Replace each angle-bracket placeholder below with the value you recorded.
  • Insert only the build options already required by your bootcamp application.
  • Build the versioned image by running the completed command:
docker build --tag <docker-hub-username>/<repository>:<version-tag> <build-context>

What Does This Command Do?

  • The --tag option assigns the full repository plus version tag to the finished image.
  • The <build-context> value selects the files available to the existing container build definition.
  • Your existing build options preserve any application-specific requirements from the bootcamp workflow.

The completed build leaves the source layout plus the existing container build definition unchanged. Docker now stores the versioned image locally.

  • Confirm the exact image reference by running:
docker image ls <docker-hub-username>/<repository>:<version-tag>

What Does This Check Show?

The filter limits the image list to the repository plus version tag you just built. Its matching row includes the local image ID that identifies the built artifact.

Good progress. Your application now exists as a locally stored release with an explicit version identity.

  • Record the displayed image ID as your image ID.

Can't Find the Tagged Image?

Compare the username plus repository plus tag against the values used in the build command. A difference in any one value produces a different image reference.

Confirm that the build context points to the existing application files. Reapply any build options required by your bootcamp workflow.

Help me diagnose my local Docker image build.

Run the local proof

Docker port publishing connects a port on your workstation to the application's listening port inside the container. This creates the same host-to-container boundary you later reproduce on EC2.

Before you start the container, do you expect the application to be reachable through the host port you selected?

  • Replace each angle-bracket placeholder below with the value you recorded.
  • Start the versioned image as a temporary container by running:
docker run --detach --name <local-container-name> --publish <local-host-port>:<container-port> <docker-hub-username>/<repository>:<version-tag>

How Does the Container Start?

  • The --detach option runs the container in the background.
  • The --name option gives the temporary container a reusable local name.
  • The --publish option maps the selected workstation port to the application's internal port.
  • The final image reference selects the exact release you built.
  • Enter http://localhost:<local-host-port> in your browser's address bar.
  • Load the local application page.

You'll see the bootcamp application behave as expected through the local host port. That browser result proves the packaged release can serve the application before any cloud resources are involved.

  • Confirm the running container plus its port mapping by running:
docker ps

What Does the Container List Prove?

The running container row connects the temporary container name to the tagged image. Its port details show the <local-host-port>:<container-port> path used by your browser.

You'll see <local-container-name> using <docker-hub-username>/<repository>:<version-tag>. You'll also see the selected host port published to the application port.

  • Inspect the application's container output by running:
docker logs <local-container-name>

What Do the Logs Confirm?

The logs connect the browser result to the process running inside the container. Application startup output also helps you spot a wrong internal port or an early process exit.

🙋‍♀️ Does the Local Page Stay Unavailable?

Compare the published host port against the URL in your browser. Confirm that the container port matches the port where your application listens.

Check the container list for an exited or missing container. Use the logs you just retrieved to identify application startup problems.

Help me diagnose my local container test.

💡 Why Does EC2 Need a Registry?

This image currently exists only in the Docker image store connected to your workstation. A remote EC2 instance cannot read that local store.

Docker Hub becomes the handoff point between the build workstation and the deployment server. Publishing the tested tag there lets another machine retrieve the same artifact.

  • Return to your project deployment notes from earlier.
  • Record the original image tag <version-tag>.
  • Record the local image ID your image ID.
  • Record the successful local browser result.
  • Record the port mapping <local-host-port>:<container-port>.
  • Explain why EC2 needs a registry to retrieve the locally built image.
  • Stop the temporary test container by running the first command below.
  • Remove the stopped test container by running the second command below:
docker stop <local-container-name>
docker rm <local-container-name>

Why Remove the Test Container?

Stopping the container ends the local application process cleanly. Removing it releases the temporary container name without deleting the versioned image.

Before you check, do you expect the removed test container to remain in the running container list?

  • Confirm the temporary container is gone by running:
docker ps

What Should You See?

The running container list no longer includes <local-container-name>. The tagged image remains available for publishing in the next step.

You have proved that the exact versioned image works through its host-to-container port mapping. Next, you'll publish that tested artifact so the EC2 deployment server can retrieve it.

Publish the Versioned Image

Your tested image already proves that the bootcamp application works inside a local Docker container. Amazon EC2 still cannot retrieve an image that exists only on your workstation.

An image registry gives another machine a place to retrieve that tested artifact. Docker Hub becomes the handoff point for the exact version you already proved locally.

In this step, get ready to:
  • Create or reuse the private Docker Hub repository for the tested image.
  • Push the tested image under its explicit version tag.
  • Verify the remote tag against the push digest.
Create or reuse the private repository

Docker Personal allows up to one private repository. Reusing the chosen private repository keeps this project within that allowance.

Why Docker Hub for This Deployment?

Docker Hub keeps the manual registry handoff visible. Your workstation pushes the tested image before the remote server pulls it.

Amazon ECR remains outside this manual baseline. This keeps your attention on the deployment workflow that later automation replaces.

Choose the path that matches the private repository in your Docker Hub account.

Reuse Existing Repository

This path applies when the private repository already exists under your Docker Hub namespace.

  • Return to Docker Hub in your browser.
  • Select My Hub.
  • Select Repositories.
  • Select <repository> under <docker-hub-username>.
  • Confirm the repository visibility is private.

You should see the repository path <docker-hub-username>/<repository> with private visibility.

Create Private Repository

This path applies when the chosen repository does not exist yet.

  • Return to Docker Hub in your browser.
  • Select My Hub.
  • Select Repositories.
  • Select Create repository.
  • Choose <docker-hub-username> as the namespace.
  • Enter <repository> as the repository name.
  • Set the repository visibility to private.
  • Select Create repository.

You should see the new repository at <docker-hub-username>/<repository> with private visibility.

Your private Docker Hub destination is ready. The tested image now has a remote repository waiting for it.

Preserve the tested version in the registry

The explicit tag identifies the release you tested locally. The push digest gives that uploaded image a content-based identity.

Before you push, which tag do you expect Docker Hub to store: latest or <version-tag>? Make your prediction now.

  • Return to the authenticated WSL Ubuntu terminal from earlier.
  • Upload the tested release to its private repository by running this command:
docker push <docker-hub-username>/<repository>:<version-tag>

What Does This Command Do?

  • The repository path sends the image to the matching Docker Hub namespace.
  • The <version-tag> value preserves the immutable release name you tested locally.
  • The final digest identifies the uploaded image content.

The terminal reports each uploaded layer. The final output includes the pushed tag plus its digest.

  • Record the final digest in your project deployment notes: your push digest.

Does the Push Fail?

  • Confirm the repository path matches <docker-hub-username>/<repository>.
  • Repeat the browser-based login flow if your earlier Docker Hub authentication has expired.
  • Confirm the private repository belongs to the namespace in the image name.

Help me diagnose the failed image push.

Verify the remote release

A successful terminal push proves that Docker accepted the upload. The repository page confirms that the expected release exists at the remote handoff point.

Before you check, do you expect the remote tag plus digest to match the values from your push? Hold that prediction for the comparison.

  • Return to the private Docker Hub repository from earlier.
  • Select the Tags tab.
  • Find the exact tag <version-tag>.
  • Compare its displayed digest with your push digest.
  • Record <docker-hub-username>/<repository> as the private repository in your project deployment notes.
  • Record <version-tag> as the explicit pushed tag in your project deployment notes.
  • Keep every credential out of your project deployment notes.

You should see <version-tag> on the Tags page. Its digest should match the value recorded from the push output.

That completes the registry handoff. Docker Hub now holds the same version you tested locally.

Can't Find the Tag?

  • Confirm that you opened the repository under <docker-hub-username>.
  • Check that the terminal push completed before refreshing the Tags page.
  • Confirm that you searched for <version-tag> instead of latest.

Help me find my pushed Docker Hub tag.

Your tested release is now available beyond your workstation. Next, you will prepare an EC2 server to pull that exact image.

Launch and Prepare the EC2 Server

Your tested image now lives in Docker Hub. The next handoff needs a remote host that can retrieve that exact artifact.

Publishing an image does not deploy it. In this step, you will launch an Amazon EC2 instance with Amazon Linux 2023. You will connect through SSH. You will use Docker to run the same version you tested locally.

In this step, get ready to:
  • Launch an EC2 instance with an SSH-only inbound path.
  • Secure the private key inside your WSL home directory.
  • Pull the versioned image onto EC2 and run its container.
Launch the EC2 instance

The AWS Management Console turns an Amazon Machine Image into a running virtual server. A security group controls which inbound requests can reach that server.

Know What Starts Accruing Usage

Launching this instance creates AWS resources that can accrue charges. You already checked your account's Free Tier or credit status.

Use one short-lived instance for this project. The cleanup section shows how to stop or terminate it after you capture your evidence.

  • Return to the AWS Management Console from earlier.
  • Confirm that the console still shows your selected AWS Region.
  • Select EC2 from the services menu.
  • Choose Launch instance.
  • Enter <instance-name> in the Name and tags section.
  • Select an Amazon Linux 2023 AMI owned by Amazon that the console marks Free Tier eligible for your account.
  • Select an instance type that the console marks Free Tier eligible for your account.
  • Create <key-pair-name> as a new key pair in the Key pair (login) section.

Why Amazon Linux 2023?

Amazon Linux 2023 provides a documented EC2 path for Docker installation. Its default SSH user is ec2-user.

Ubuntu uses different package commands plus a different default username. Keeping one operating system makes the remote deployment repeatable.

Creating the key pair downloads <key-pair-name>.pem to Windows. Keep that file private because it grants SSH access to the instance.

  • Choose the default VPC in Network settings.
  • Choose a public subnet with public IPv4 assignment enabled.
  • Create <security-group-name> as the instance security group.
  • Add one inbound SSH rule using TCP port 22.
  • Set the SSH rule source to your current public IP.
  • Confirm that no inbound rule permits <ec2-host-port>.
  • Keep the default root volume in Configure storage.
  • Choose Launch instance in the summary panel.

Provisioning can take a few minutes while AWS starts the virtual server. The initial instance state shows pending during this process.

  • Choose the instance ID from the successful launch notification.
  • Wait until the instance state shows running.
  • Wait until the instance passes its status checks.
  • Record the displayed public IPv4 address as <instance-public-ip>.
  • Record the displayed public DNS name as <instance-public-dns>.
  • Record the AMI plus instance type in your project deployment notes.

Protect Public Details

A public IPv4 address is not a password. You can still redact it from portfolio screenshots if your privacy policy requires that.

Secure the key and connect with SSH

A key pair proves that your SSH client is allowed to connect. Linux file permissions keep the downloaded private key readable only by you.

The private key unlocks access to your server. Store it in your WSL home directory without committing it or uploading it.

  • Return to your WSL Ubuntu terminal from earlier.
  • Open your WSL home directory in File Explorer by running these commands:
cd ~
explorer.exe .

What Do These Commands Do?

  • The first command moves the terminal into your WSL home directory.
  • The second command opens that directory in Windows File Explorer.
  • Select Downloads in a separate File Explorer window.
  • Move <key-pair-name>.pem into the open WSL home directory.
  • Return to your WSL Ubuntu terminal.
  • Restrict the private key permissions by running this command:
chmod 400 <key-pair-name>.pem

What Does This Command Do?

The permission mode allows only your WSL user to read the private key. SSH rejects a private key when its permissions are too open.

  • Switch back to the EC2 console.
  • Select <instance-name> on the Instances page.
  • Choose Actions.
  • Choose Monitor and troubleshoot.
  • Choose Get system log.
  • Find the fingerprints under BEGIN SSH HOST KEY FINGERPRINTS.

The system log gives you an independent fingerprint for the server. Keep this log visible for the first connection.

  • Return to the Instances page.
  • Select <instance-name>.
  • Choose Connect.
  • Select the SSH client tab.
  • Connect from WSL using the exact generated command in this general form:
ssh -i <path-to-key-pair.pem> ec2-user@<instance-public-dns>

What Does This Command Do?

  • The -i option points SSH at the private key in your WSL home directory.
  • The ec2-user account is the default login identity for Amazon Linux.
  • The public DNS name routes the connection to your running EC2 instance.
  • Compare the fingerprint shown by SSH with the matching fingerprint in the EC2 system log.
  • Enter yes only after the fingerprints match.

You will see an Amazon Linux terminal prompt for ec2-user. That proves your SSH-only path reaches the instance.

Unable to Connect Through SSH?

Confirm that the private-key path points to the file in your WSL home directory. Confirm that the instance has passed its status checks.

Check that the SSH rule still uses your current public IP. A changed home or office IP requires the rule source to be updated.

Help me diagnose my EC2 SSH connection.

Install Docker and run the image

Amazon Linux 2023 uses DNF to install packages. Docker also needs a running service plus group membership before ec2-user can run containers without elevated privileges.

  • Install Docker and prepare its service by running these commands on EC2:
sudo dnf install -y docker
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -a -G docker ec2-user

What Do These Commands Do?

  • The first command installs Docker from the Amazon Linux 2023 repositories.
  • The next command starts Docker for the current session.
  • The enable command configures Docker to start after a server reboot.
  • The final command adds ec2-user to the Docker group.

The installation can take a minute while DNF downloads the package. The terminal returns to the prompt after all four commands finish.

  • Close the current SSH terminal window so the new group membership can apply.
  • Press the Windows key to open Windows search.
  • Type Ubuntu into Windows search.
  • Press Enter to open WSL Ubuntu.
  • Reconnect using the same SSH command from above.
  • Verify Docker access by running these commands:
docker version
docker info

What Should You See?

The first command prints both Client and Server sections. The second command prints system-wide Docker information without requiring sudo.

That output confirms Docker is running. It also confirms that the group change applies to your new SSH session.

Docker Server Section Missing?

Confirm that you closed the original SSH session after changing the group. Reconnect before running the checks again.

Confirm that the Docker service started successfully. A package installation failure must be resolved before the service can run.

Help me restore Docker access on EC2.

The private repository requires a Docker Hub personal access token on the remote server. Create a read-only token so EC2 can pull the image.

  • Switch to Docker Home in your browser.
  • Select your avatar in the top-right corner.
  • Select Account settings.
  • Select Personal access tokens.
  • Select Generate new token.
  • Enter <instance-name> in the Access token description field.
  • Select Repo Read-only for the repository permission.
  • Select Generate.

Docker shows the token once. Copy it directly into a credential manager so it never enters your notes or screenshots.

  • Copy the generated token into your credential manager.
  • Return to your EC2 SSH session.
  • Start the Docker Hub login by running this command:
docker login -u <docker-hub-username>

What Happens During Login?

Docker prompts for a password after you run the command. Paste the personal access token at that prompt.

The terminal does not display the token while you paste it. Successful authentication allows this EC2 host to pull your private image.

🙋‍♀️ Docker Hub Login Rejected?

Confirm that the username owns the token. Paste the full token without extra spaces or line breaks.

Check that the token is active. Confirm that it has read access to private repositories.

Help me diagnose my Docker Hub login.

  • Pull the tested image onto EC2 by running this command:
docker pull <docker-hub-username>/<repository>:<version-tag>

What Does This Command Do?

Docker Hub supplies the same immutable tag that passed your local test. The pull output shows the layers plus the image digest retrieved by EC2.

The registry has now completed its handoff. Your workstation and EC2 can reference the same artifact.

  • Record a remote container name as <remote-container-name>.
  • Record the EC2 host port as <ec2-host-port>.
  • Start the pulled image with your container name plus port mapping by running this command:
docker run --detach --name <remote-container-name> --publish <ec2-host-port>:<container-port> <docker-hub-username>/<repository>:<version-tag>

What Does This Command Do?

  • The --detach option keeps the container running in the background.
  • The --name option assigns the remote container name you recorded.
  • The --publish option maps the EC2 host port to the application's container port.
  • The final value selects the exact image tag pulled from Docker Hub.

The terminal prints a container identifier. Your application process is now running on the EC2 host.

Before you inspect Docker, what image tag plus port mapping do you expect the running-container list to report?

  • Inspect the running container plus its application logs by running these commands:
docker ps
docker logs <remote-container-name>

What Should You See?

The running-container list shows <remote-container-name> with the image tag you pushed. Its ports column shows the mapping from <ec2-host-port> to <container-port>.

The logs show the startup behavior of your existing bootcamp application. This proves the image runs on EC2.

🙋‍♀️ Container Missing or Exited?

Check that the image reference contains your Docker Hub username plus repository plus explicit version tag. Confirm that the container name is not already assigned to another container.

Use the displayed application logs to find a missing runtime setting or port mismatch from your existing bootcamp configuration.

Help me diagnose my EC2 container.

Before you load the public URL, do you think Docker's published port alone lets the browser request reach the container?

  • Switch to your browser.
  • Enter http://<instance-public-ip>:<ec2-host-port> in the address bar.
  • Load the application URL.

The page remains unreachable. This planned shortfall occurs even though Docker reports a running container plus the correct port mapping.

What Does the Blocked Request Prove?

Docker accepts traffic that reaches the EC2 host port. The security group currently authorizes inbound SSH traffic only.

The browser request stops at the AWS network boundary before it reaches Docker. You have now isolated the missing link in the deployment path.

  • Record the running EC2 state in your project deployment notes.
  • Record the Amazon Linux 2023 AMI in your notes.
  • Record the selected instance type in your notes.
  • Record that SSH remains restricted to your current public IP.
  • Record the successful SSH session plus Docker version.
  • Record the pulled image tag plus running remote container.
  • Record the intentionally blocked browser request.
  • Record that no inbound rule permits <ec2-host-port>.

Deployment Checkpoint

Your Amazon Linux 2023 instance is running in the selected Region. It uses the default VPC plus a public subnet plus the default root volume.

Docker runs <docker-hub-username>/<repository>:<version-tag> as <remote-container-name>. External browser access remains blocked by the security group.

Your tested image now runs on a remote server. Next, you will open the application path while keeping SSH restricted to your IP.

Open the Application Network Path

The tagged image is already running through Docker on your remote server. Its blocked public URL exposed a gap between port publishing and the Amazon EC2 security group.

This step authorizes the application port for your public demonstration. Your SSH rule stays restricted to your current public IP.

In this step, get ready to:
  • Add a Custom TCP rule for the application port.
  • Confirm the running image plus its published port mapping.
  • Load the public application plus capture the deployment evidence.
Add the application inbound rule

An inbound rule decides which internet traffic can reach your EC2 instance. Opening a port to the internet is a security-sensitive change.

The new rule exposes only <ec2-host-port> for the intentional public demonstration. Port 22 remains limited to your current public IP.

  • Return to the AWS Management Console from earlier in your selected Region.
  • Select <instance-name> from the EC2 instance list.
  • Open the attached security group named <security-group-name>.
  • Choose Edit inbound rules.

You should see the existing SSH rule. Its source should still be your current public IP.

  • Choose Add rule.
  • Select Custom TCP as the rule type.
  • Enter <ec2-host-port> as the application port.
  • Enter 0.0.0.0/0 as the source for the public demonstration.
  • Confirm the SSH rule still restricts TCP port 22 to your current public IP.
  • Save the inbound rules.

You should now see two separate inbound rules. The new rule applies automatically to <instance-name>.

Why Keep the Rules Separate?

The application rule admits browser traffic on <ec2-host-port>. Docker forwards that traffic to <container-port> inside the container.

The SSH rule controls administrative access to the server. Restricting it to your current public IP reduces who can attempt a connection.

🙋‍♀️ Unable to Save the Rule?

Confirm that the new rule uses Custom TCP with <ec2-host-port> as its port. Check that the source contains 0.0.0.0/0.

Make sure you are editing <security-group-name>. It must be the security group attached to <instance-name>.

Help me fix the application inbound rule.

Confirm the published container path

The security group now admits the request to the EC2 host port. The running container must still publish that host port to the application port.

  • Switch back to the SSH session from earlier.
  • Confirm the container remains active by running this command:
docker ps

What Does This Check?

  • The command lists the containers currently running on the EC2 instance.
  • The image reference identifies the deployed tag.
  • The port mapping connects <ec2-host-port> on the host to <container-port> in the container.

You should see <remote-container-name> running from <docker-hub-username>/<repository>:<version-tag>. Its published mapping should show <ec2-host-port>:<container-port>.

Container Missing From the List?

Confirm that your SSH session is connected to <instance-name>. A connection to another host shows a different container list.

Check your prior deployment notes for the container name plus image tag. The running entry should use the original immutable tag.

Help me diagnose the missing EC2 container.

Load and document the public deployment

Before you refresh, which layer should now admit the browser request that failed earlier?

  • Switch back to the browser from the blocked-port test.
  • Enter http://<instance-public-ip>:<ec2-host-port> in the address bar.
  • Load the application URL.

Your bootcamp application should now load from the EC2 instance. The previously blocked request can cross the new security group rule.

  • Switch back to the SSH session from earlier.
  • Inspect the application logs by running this command:
docker logs <remote-container-name>

What Do the Logs Prove?

The logs come from the same container that serves the public page. They connect the browser result to the running application process.

You should see runtime output from the application without a startup failure. That is the full manual deployment path working from browser to container.

Public Page Still Unavailable?

Confirm that the browser URL uses the public IPv4 address for <instance-name>. Confirm that it uses <ec2-host-port> after the colon.

Check that <security-group-name> contains the new application rule. Check that the running container still shows <ec2-host-port>:<container-port> as its mapping.

Help me trace the blocked browser request.

Your deployment evidence needs to show each handoff in the request path. This turns a working page into a deployment story you can explain.

  • Capture the final application page at http://<instance-public-ip>:<ec2-host-port>.
  • Capture the SSH rule plus the Custom TCP application rule.
  • Record the running image reference <docker-hub-username>/<repository>:<version-tag>.

Your evidence now shows the public result plus the controls that permit it.

  • Add the browser-to-security-group-to-host-port-to-container-port request path to your project deployment notes.
  • Add a short comparison of the local Docker command with the EC2 Docker command.

Your notes now connect the local test to the public release.

  • Summarize the deployment problem plus the architecture in your portfolio entry.
  • Explain the blocked-port diagnosis plus the security decision in your portfolio entry.

The blocked request gives your write-up a concrete diagnosis. The successful refresh supplies the fix.

  • Add the cost controls plus the manual actions that Jenkins should automate next.

You have completed the manual path from a local image to a public original release. Every future automation step now has a proven baseline.

Secret mission

Re-deploy and Roll Back a Version

Build a second tagged release from the next state of your existing bootcamp application. Deploy it manually on EC2. Restore the original tag to prove your rollback path.

Clean Up Your Resources

Clean Up Your Resources

Choose whether to keep the deployment live, stop it for Part 2, or remove it completely. Keeping the AWS resources running can continue generating charges.

Cost warning

An assigned public IPv4 address costs $0.005 per hour while in use or idle. Amazon EC2 and Amazon EBS can add regional charges when credits or Free Tier allowances do not cover them.

Stopping the instance preserves its EBS-backed state, so storage can remain billable. Termination is the safest choice after you have captured your evidence.

Docker Personal remains $0 within its plan limits.

Resources you used:

  • The private Docker Hub repository <docker-hub-username>/<repository> containing tags <version-tag> and <second-version-tag>.
  • The running Amazon Linux 2023 instance <instance-name> with its default root EBS volume, assigned public IPv4 address, and restored Docker container <remote-container-name>.
  • The security group <security-group-name> with its restricted SSH rule and public application-port rule.
  • The EC2 key pair <key-pair-name> and its SSH private key <key-pair-name>.pem in your WSL home directory.

Keep everything running

No action is needed. Choose this if you need the public application for an immediate demonstration.

  • Leave the current EC2 deployment running.
  • Keep <security-group-name> attached with SSH restricted to your current public IP.
  • Keep <docker-hub-username>/<repository> with both explicit version tags.
  • Store <key-pair-name>.pem outside your application source.
  • Keep the private key out of commits, uploads, and project screenshots.

Your public application remains available. AWS usage can continue generating charges.

Pause - I'll come back to this later

Stop the instance to pause its compute usage while preserving the deployment for Part 2. The attached root volume can remain billable.

  • Return to the EC2 instance list in the AWS Management Console.
  • Select <instance-name>.
  • Choose Instance state.
  • Choose Stop instance.
  • Confirm the stop action.
  • Refresh http://<instance-public-ip>:<ec2-host-port> in your browser.

The public application no longer loads. This confirms that the instance has stopped serving traffic.

Your root EBS volume remains attached. A later start normally receives a new public IPv4 address.

Delete - I don't want to use this again

Removing this deployment is permanent. Your deployment notes remain available after the cloud resources are gone.

  • Return to the SSH connection for <instance-name>.
  • Log the EC2 host out of Docker Hub by running this command:
docker logout

What does this command do?

This removes the saved Docker Hub authentication from the EC2 host before you terminate it.

🙋‍♀️ Can't log out?

  • Confirm that your terminal prompt belongs to <instance-name>.
  • Retry the command after confirming that the EC2 host still has internet access.
  • Help me troubleshoot Docker Hub logout on my EC2 instance.
  • Return to the EC2 instance list in the AWS Management Console.
  • Select <instance-name>.
  • Choose Instance state.
  • Choose Terminate (delete) instance.
  • Confirm the termination.

The status can take a little time to update. That delay is expected while AWS finishes the termination.

  • Wait until the instance state changes to terminated.
  • Refresh http://<instance-public-ip>:<ec2-host-port> in your browser.

The public application no longer loads. This confirms that the deployment is no longer serving traffic.

  • Check the EC2 volume list for the root volume that belonged to <instance-name>.
  • Delete the root volume if it still appears after termination.
  • Confirm that the root volume no longer appears in the volume list.
  • Return to the EC2 security group list.
  • Select <security-group-name>.
  • Delete the selected security group.
  • Return to the EC2 key pair list.
  • Delete <key-pair-name> if you do not plan to reuse it.

You should no longer see the project instance, root volume, security group, or unused key pair in the selected AWS Region.

  • Return to Docker Hub.
  • Select My Hub.
  • Select Repositories.
  • Open <docker-hub-username>/<repository>.
  • Use the repository deletion control to remove <docker-hub-username>/<repository> if you no longer need either image tag.
  • Confirm that the repository no longer appears under Repositories.
  • Remove the downloaded private key from your WSL home directory by running this command:
rm ~/<key-pair-name>.pem

Why remove the local key?

The private key no longer provides useful access after its EC2 key pair and instance are deleted. Removing the file prevents it from being copied into another project later.

🙋‍♀️ Key file still present?

  • Check that the filename in your WSL home directory matches <key-pair-name>.pem.
  • Remove any additional copy from the location where you originally saved it.
  • Help me find and safely remove my EC2 private key.
  • Inspect your WSL home directory.

The file <key-pair-name>.pem no longer appears there.

Nice Work!

Nice Work!

You did it! Your existing bootcamp application now runs publicly on Amazon EC2 from the exact Docker image you tested locally.

You've learned how to:

  • Package your existing application as a versioned Docker image. Prove the image works locally before cloud deployment.
  • Promote the tested image through Docker Hub. Pull the exact tag onto Amazon EC2 without changing the application's source layout.
  • Diagnose a blocked browser request by tracing the security group path and Docker port mapping. Preserve deployment evidence that identifies the manual tasks Jenkins should automate next.
  • Secret Mission: Deploy a second explicit tag. Restore the original release through a manual rollback.

Ready to quiz yourself?