# Containerizing and Deploying a React App: From Local to EC2

In this post, we'll walk through the process of containerizing a React application, pushing it to Docker Hub, and deploying it on an Amazon EC2 instance. We'll dive deep into each step, exploring best practices and uncovering some pro tips along the way.

### Link to our Github Codebase

%[https://github.com/SundayPyjamas/personal-site] 

Docker image can be found on [Docker Hub](https://hub.docker.com/repository/docker/prathameshrr/personal-site/general).

### 1\. Containerizing the React App

Let's start by creating a Dockerfile for our React application. Here's the Dockerfile we'll use:

```dockerfile
# Use an official Node runtime as the base image
FROM node:14-alpine

# Set the working directory in the container
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Build the app
RUN npm run build

# Use nginx to serve the static files
FROM nginx:alpine

# Copy the build output to replace the default nginx contents
COPY --from=0 /app/build /usr/share/nginx/html

# Expose port 80
EXPOSE 80

# Start nginx
CMD ["nginx", "-g", "daemon off;"]
```

This Dockerfile uses a multi-stage build process. The first stage builds our React app, and the second stage sets up Nginx to serve the built files.

**Pro Tip:** Using Alpine-based images significantly reduces the size of your container, making it faster to push and pull from registries.

To build the Docker image, run:

```bash
docker build -t personal-site .
```

### 2\. Pushing to Docker Hub

Before pushing our image, let's tag it with our Docker Hub username:

```bash
docker tag personal-site yourusername/personal-site:latest
```

Now, let's push it to Docker Hub:

```bash
docker push yourusername/personal-site:latest
```

**Pro Tip:** Consider using semantic versioning for your tags (e.g., v1.0.0) in addition to the 'latest' tag. This allows for easier rollbacks and version tracking.

### 3\. Deploying on EC2

Now that our image is on Docker Hub, let's deploy it on an EC2 instance.

1. Launch an EC2 instance (I used an Amazon Linux 2 AMI).
    
2. SSH into your instance:
    

```bash
ssh -i "your-key.pem" ec2-user@your-ec2-public-dns
```

3. Install Docker on the EC2 instance:
    
    1. Update your system packages:
        
        ```plaintext
        sudo yum update -y
        ```
        
    2. Install Docker:
        
        * For Amazon Linux 2023:
            
            ```plaintext
            sudo yum install -y docker
            ```
            
    3. Start the Docker service:
        
        ```plaintext
        sudo service docker start
        ```
        
    4. Enable Docker to start on boot:
        
        ```plaintext
        sudo systemctl enable docker
        ```
        
    5. Add your user (e.g., ec2-user) to the docker group to run Docker commands without sudo:
        
        ```plaintext
        sudo usermod -a -G docker ec2-user
        ```
        
    6. Log out and log back in for the group changes to take effect, or run:
        
        ```plaintext
        newgrp docker
        ```
        
    7. Verify the installation:
        
        ```plaintext
        docker --version
        ```
        
    8. To test if Docker is working correctly, you can run:
        
        ```plaintext
        docker info
        ```
        
    
    If you need docker-compose as well, you can install it using:
    
    ```plaintext
    sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    sudo chmod +x /usr/local/bin/docker-compose
    ```
    
    After installation, you can verify docker-compose is installed correctly by running:
    
    ```plaintext
    docker-compose version
    ```
    
    Remember to reboot your instance if you encounter any permission issues:
    
    ```plaintext
    sudo reboot
    ```
    
    These steps should get Docker up and running on your Amazon Linux EC2 instance
    
4. Log out and log back in to apply the group changes.
    
5. Pull and run your Docker image:
    

```bash
docker pull yourusername/personal-site:latest
docker run -d -p 80:80 yourusername/personal-site:latest
```

**Pro Tip:** Use Docker Compose for more complex deployments involving multiple containers or environment-specific configurations.

### 4\. Security Considerations

Remember to configure your EC2 security group to allow inbound traffic on port 80. Also, consider setting up HTTPS using Let's Encrypt for production deployments.

**Curiosity Spark:** How would you implement blue-green deployments using this setup? Think about how you could use Docker tags and EC2 load balancers to achieve zero-downtime deployments.

### 5\. Monitoring and Logging

For production deployments, consider integrating with AWS CloudWatch for monitoring and logging. You can use the awslogs log driver when running your container:

```bash
docker run -d -p 80:80 --log-driver=awslogs --log-opt awslogs-group=my-app-logs yourusername/personal-site:latest
```

**Pro Tip:** Implement health checks in your container to ensure your application is responding correctly. You can add a HEALTHCHECK instruction to your Dockerfile for this.

### 6\. Optimizing for Production

To further optimize your containerized app for production:

1. Use multi-stage builds to keep your final image small.
    
2. Implement caching strategies for your Nginx server.
    
3. Consider using a Content Delivery Network (CDN) like AWS CloudFront for global distribution.
    

**Curiosity Spark:** How would you implement auto-scaling for your containerized app on EC2? Research EC2 Auto Scaling groups and how they can be used with containerized applications.

### Conclusion

Containerizing and deploying a React app involves several steps, each with its own set of best practices and optimization opportunities. By following this guide, you've not only deployed your app but also set up a foundation for scalable, maintainable, and efficient cloud-native applications.
