OpenTofu infra for deploying on ec2 #232
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds OpenTofu (Terraform-compatible) infrastructure-as-code for deploying the TEKDB application on AWS EC2, along with restructured Docker Compose files that separate dev/prod configurations, and a new GitHub Actions workflow to publish Docker images.
Changes:
- New
infra/directory with complete OpenTofu configuration for AWS EC2, ECR, IAM, networking, and outputs. - Restructured Docker Compose setup using a shared
common.yamlbase with environment-specific overrides (docker-compose.yaml,docker-compose.prod.yaml,docker-compose.prod.local.yaml). - Application changes: nginx upstream renamed from
apptoweb, uWSGI switched from HTTP to socket mode for production, new CI/CD workflow for building and publishing Docker images.
Reviewed changes
Copilot reviewed 18 out of 20 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
infra/terraform.tf |
OpenTofu backend (S3) and provider version constraints |
infra/main.tf |
AWS provider, variable declarations |
infra/ec2.tf |
EC2 instance, key pair, and Elastic IP resources |
infra/ecr.tf |
ECR repositories for web and proxy images |
infra/iam.tf |
IAM role and instance profile for ECR access |
infra/networking.tf |
Security group with HTTP/HTTPS/SSH ingress |
infra/outputs.tf |
Terraform outputs for EC2 IP and ECR URLs |
infra/user_data.sh |
EC2 bootstrap script installing Docker, AWS CLI, Git |
infra/.terraform.lock.hcl |
Lock file pinning AWS provider to 5.100.0 |
proxy/default.conf |
Nginx upstream renamed from app to web |
proxy/Dockerfile |
Reordered to copy-then-chmod and moved USER root before COPY |
TEKDB/Dockerfile |
Removed default CMD ["dev"] |
TEKDB/TEKDB/settings.py |
SQL_PORT default changed from None to 5432 |
TEKDB/entrypoint.sh |
Added prod-local mode using HTTP (vs socket) uWSGI |
docker/common.yaml |
Shared base service definitions extracted for DRY compose setup |
docker/docker-compose.yaml |
Dev compose using common.yaml base |
docker/docker-compose.prod.yaml |
Production compose using ECR images and nginx proxy |
docker/docker-compose.prod.local.yaml |
New prod-local variant for local production testing |
.github/workflows/create-and-publish-docker-images.yml |
CI workflow to build and push web Docker image to GHCR |
.gitignore |
Added .env.prod, OpenTofu state files, and .tfvars patterns |
Files not reviewed (1)
- infra/.terraform.lock.hcl: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| push: true | ||
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/web:latest,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/web:${{ github.sha }} | ||
| labels: ${{ steps.meta.outputs.labels }} | ||
|
|
There was a problem hiding this comment.
This workflow only builds and pushes the web image to GHCR. However, docker/docker-compose.prod.yaml references ${ITKDB_PROXY_ECR_PATH}:latest for the proxy service, and infra/ecr.tf creates an aws_ecr_repository for the proxy. There is no step in this workflow (or any other visible workflow) that builds and pushes the proxy image. Without a published proxy image, the production deployment will fail when it attempts to pull it. A separate build step for the proxy image (context: ./proxy, file: ./proxy/Dockerfile) should be added.
| - name: Build and push proxy Docker image | |
| id: push_proxy | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./proxy | |
| file: ./proxy/Dockerfile | |
| push: true | |
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/proxy:latest,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/proxy:${{ github.sha }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| @@ -42,5 +42,3 @@ ENV DJANGO_SETTINGS_MODULE=TEKDB.settings | |||
|
|
|||
| ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] | |||
|
|
|||
There was a problem hiding this comment.
The TEKDB/Dockerfile removes the default CMD ["dev"] with no replacement. With no CMD, and ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] set, running the container with no command argument means entrypoint.sh receives no arguments. The entrypoint.sh else branch does exec "$@", which with no arguments will try to execute an empty string and fail. A default CMD should be provided (e.g. CMD ["dev"]) or the entrypoint script should handle the no-argument case gracefully.
| CMD ["dev"] |
| env_file: | ||
| - .env.prod |
There was a problem hiding this comment.
The web service in docker-compose.prod.yaml adds env_file: [.env.prod] via extends from common.yaml which already has env_file: [.env.dev]. Docker Compose merges list-type keys when using extends, so both .env.dev and .env.prod will be loaded. Values from .env.prod will take precedence over .env.dev (last file wins) when both define the same key, but the development secrets from .env.dev will still be passed into the container as well. If .env.dev is not present on the production server this may cause a startup failure. Consider explicitly overriding env_file to only include .env.prod rather than relying on merge behavior.
| extends: | ||
| file: common.yaml | ||
| service: web | ||
| image: ${ITKDB_ECR_PATH}:latest |
There was a problem hiding this comment.
The workflow pushes images to GHCR (GitHub Container Registry at ghcr.io), but the production Docker Compose file uses ${ITKDB_ECR_PATH} and ${ITKDB_PROXY_ECR_PATH}, which are Amazon ECR paths. The infra code also provisions ECR repositories (infra/ecr.tf). There is a mismatch: this workflow doesn't publish to ECR at all, and there's no workflow in place to authenticate with AWS ECR and push there. Either the docker-compose.prod.yaml should point to GHCR images, or this workflow needs to be updated to authenticate and push to ECR.
|
@rhodges @pollardld would love your eyes on this if you have a chance! Some new things that I have added in the past two days:
|
|
I will asap. Probably tmrw morning. |
| on: | ||
| push: | ||
| branches: | ||
| - develop |
There was a problem hiding this comment.
changed to deploy to ec2 staging on push to the develop branch. Need to add to the ec2 user data script to switch to the develop branch. But this needs to be merged first. kind of a 🐔 and 🥚 situation
pollardld
left a comment
There was a problem hiding this comment.
This is awesome. Excited to learn and use this!
Adds OpenTofu and docker set up for deploying on EC2
Instructions for deploying to EC2 (to be added to wiki when this is merged)
How to deploy to EC2:
/infra/directory initialize OpenTofu:tofu inittofu applyssh -i ~/.ssh/id_ed25519 ubuntu@<public_ip>cd tekdbgit clone https://github.com/Ecotrust/TEKDB.gitgit checkout <branch-name>docker/.env.prod. contact your system admin for these:a.
aws ecr get-login-password --region us-west-2 | sudo docker login --username AWS --password-stdin <web-ecr-path>b.
aws ecr get-login-password --region us-west-2 | sudo docker login --username AWS --password-stdin <proxy-ecr-path>a.
sudo docker pull <web-ecr-path>:latestb.
sudo docker pull <proxy-ecr-path>:latestTEKDB/, spin up the containers with the prod docker compose file:docker compose --env-file docker/.env.prod -f docker/docker-compose.prod.yaml up -d