Welcome back! In our last lesson, you successfully provisioned the core infrastructure for our application on AWS, setting up an EC2 instance, an RDS database, and an S3 bucket. You've prepared the cloud "real estate," and today, we're going to move our application in.
This lesson focuses on deploying the containerized Django application you built locally onto the EC2 virtual server. This is a crucial milestone that takes your project from your local machine to a live server on the internet. We will perform what's known as a "lift and shift" deployment: taking our existing docker-compose setup and running it directly on the EC2 instance. This directly addresses the job requirement of being able to "Deploy to AWS (EC2...)" and serves as the bridge between local development and a true cloud-native configuration.
By the end of this lesson, you will be able to:
- Securely connect to and configure a remote EC2 server.
- Install the necessary runtime environment (Docker).
- Transfer your application code to the server.
- Launch your containerized application in the cloud.
- Access your running application via its public IP address.
Let's begin the process of bringing your application online.
Step 1: Connecting to Your EC2 Instance
First, you need to establish a secure connection to the virtual server you created. This is done using SSH (Secure Shell) and the private key file (.pem) you downloaded when you launched the instance.
- Locate your key file: Find the
.pemfile you saved in the previous lesson (e.g.,aws-infilytics-key.pem). - Get your instance's IP: Go to your AWS EC2 console, select your running instance (
infilytics-web-server), and find its "Public IPv4 address". - Set key permissions (if needed): On Linux or macOS, your key file needs strict permissions. Open a terminal in the directory where your key is stored and run:
chmod 400 your-key-file-name.pem - Connect via SSH: Use the following command in your terminal, replacing the placeholders with your actual key file name and public IP address:
For example:ssh -i "your-key-file-name.pem" ubuntu@<your-ec2-public-ip-address>ssh -i "aws-infilytics-key.pem" ubuntu@54.123.45.67
If successful, you'll see a welcome message from Ubuntu, and your terminal prompt will change to something like ubuntu@ip-172-31-45-12:~$. You are now operating inside your cloud server.
Step 2: Preparing the Server Environment
Our EC2 instance is a bare-bones Ubuntu server. It needs Docker and Docker Compose to run our containerized application. We'll install them now.
The article from TestDriven.io provides a concise set of up-to-date commands for this process.
Deploying Django to AWS with Docker and Let's Encrypt
This guide provides the necessary commands to set up a Docker environment on an Ubuntu server. We will focus only on the installation steps.
In the article, locate the section titled "Configure EC2 Instance". You have already connected to your instance, so you can skip the first part. Focus on the subsection "Install Docker". Carefully execute each command provided in your EC2 terminal. These commands will: Update your server's package lists. Install Docker Engine. Add your user (ubuntu) to the docker group so you can run Docker commands without sudo. Install Docker Compose. After running these commands, log out of the SSH session (exit) and log back in. This step is important to apply the user group change. Once you are reconnected, you should be able to run docker --version and docker-compose --version and see their versions printed without any permission errors.
Step 3: Getting Your Application Code
With the server environment ready, you need to bring your project's source code onto the EC2 instance. The best way to do this is by cloning your Git repository.
In your EC2 terminal, run the git clone command for your project.
# Make sure you are in the home directory
cd ~
# Clone your project repository
git clone https://github.com/your-username/your-project-repo.git
# Navigate into your project directory
cd your-project-repo
Your entire project, including your Dockerfile and docker-compose.yml, is now on the server.
Step 4: Configuring the Application Environment
Just like on your local machine, your application needs its environment variables to run. Your .env file, which contains secrets, is correctly excluded from Git and was not cloned. You must create it on the server.
-
Create the file: Inside your project directory on the EC2 instance, use a simple text editor like
nanoto create the.envfile:nano .env -
Add your variables: Copy the contents of your local
.envfile and paste them into thenanoeditor. For this "lift and shift" deployment, this file should contain the credentials for the PostgreSQL Docker service, not the AWS RDS database we created. It will look something like this:# For Django SECRET_KEY=your_django_secret_key_here DEBUG=0 ALLOWED_HOSTS=* # For the Postgres container SQL_ENGINE=django.db.backends.postgresql SQL_DATABASE=infilytics_local SQL_USER=infilytics_user SQL_PASSWORD=a_strong_password_for_the_container SQL_HOST=db SQL_PORT=5432Note: The
SQL_HOSTisdb, which is the name of the database service in yourdocker-compose.ymlfile. We will change this to point to RDS in the next lesson. Using*forALLOWED_HOSTSis acceptable for now to get things working, but we will tighten this later. -
Save and exit: In
nano, pressCtrl+X, thenYto confirm you want to save, and finallyEnterto confirm the filename.
Step 5: Launching Your Application
Everything is now in place. It's time to launch the application using the same Docker Compose command you used locally.
In your project directory on the EC2 instance, run:
docker-compose up --build -d
Let's break down this command:
up: Creates and starts the containers.--build: Forces Docker to build the images from yourDockerfileon the server before starting. This is important for the first deployment.-d: Detached mode. This runs the containers in the background and frees up your terminal.
Docker will now pull the base images (like python and postgres), build your application image, and start the web and db services. This might take a few minutes.
Step 6: Verifying and Accessing Your Application
Once the command completes, you can verify that your services are running correctly.
docker ps
You should see at least two containers running: one for your Django web service and one for the db (PostgreSQL) service.
Now for the final test: accessing your application from a web browser.
- Find the public IP address of your EC2 instance.
- Find the port you exposed in your
docker-compose.ymlfile (e.g.,8000). - In your browser, navigate to
http://<your-ec2-public-ip-address>:<port>. For example:http://54.123.45.67:8000.
If you see your Django application's home page (or a "DisallowedHost" error if you didn't set ALLOWED_HOSTS), congratulations! You have successfully deployed your application to the cloud.
If it doesn't work: The most common issue is the EC2 security group. In the previous lesson, we allowed SSH, HTTP, and HTTPS. We did not explicitly allow traffic on port 8000. Go to your EC2 instance's "Security" tab, find the security group, click "Edit inbound rules," and add a new rule:
- Type: Custom TCP
- Port Range: 8000 (or whichever port your app uses)
- Source: Anywhere (0.0.0.0/0)
- Save the rules and try accessing the URL again.
Conclusion
You have achieved a massive milestone today. You've taken your self-contained, Dockerized application and deployed it to a live server on AWS. You've demonstrated the full cycle of connecting to a server, preparing its environment, transferring code, and running a multi-container application.
You've successfully:
- Connected to an EC2 instance using SSH.
- Installed Docker and Docker Compose on an Ubuntu server.
- Cloned your project and configured its environment on the server.
- Launched your application using
docker-compose.
However, our deployment is not yet optimized for the cloud. It's still using a PostgreSQL container running on the EC2 instance itself and storing files on the server's local disk. In the next lesson, we will complete the transition by reconfiguring our Django application to use the managed AWS RDS database and S3 bucket you created, making it a truly robust and scalable cloud application.