AWS Builder Center

My First CI/CD Pipeline Was Basically a Very Expensive Button

CI/CD sounded like another DevOps buzzword until I actually automated a deployment. A look at how code goes from GitHub to Docker to AWS, what CI/CD really solves, and why boring deployments are actually a good thing.

The first time I automated a deployment, I felt like I had achieved something incredible.
I pushed code.
A pipeline started.
It built my Docker image.
It pushed the image to a registry.
Then the application deployed.
I just sat there watching the logs like:
“Wait… I don't have to do any of this manually anymore?”
That was probably the moment CI/CD finally made sense to me.

Before CI/CD

The old workflow was something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Write code
↓
git push
↓
SSH into server
↓
git pull
↓
docker build
↓
docker stop
↓
docker run
↓
Pray
Technically, it worked.
But it wasn't exactly what I'd call a reliable deployment strategy.
Especially when you eventually have multiple people pushing code.
Someone forgets a command.
Someone deploys the wrong branch.
Someone builds an image with the wrong tag.
Someone says:
“It worked when I deployed it.”
And now you're investigating a production mystery at 2 AM.

Then CI entered the picture

Continuous Integration is basically about automatically checking code when changes are pushed.
A simple pipeline might do:
1
2
3
4
5
6
7
8
9
git push
↓
Build
↓
Test
↓
Lint
↓
Package
The important part isn't that the pipeline is fancy.
It's that the same checks happen consistently.
You don't have to rely on everyone remembering to run the same commands locally.
The pipeline does it for you.

Then comes the fun part: CD

Continuous Delivery/Deployment takes things further.
After the code passes its checks, you can automatically package and deploy it.
For a Docker-based application, you might have:
1
2
3
4
5
6
7
8
9
10
11
12
13
Developer
↓
GitHub
↓
CI Pipeline
↓
Run Tests
↓
Build Docker Image
↓
Push to Registry
↓
Deploy
Now a developer doesn't need SSH access to a production server just to deploy a new version.
That's a pretty significant improvement.

Docker made this even more useful

Once I started using Docker, the pipeline became much cleaner.
The pipeline could build the exact same image that would eventually run in production.
For example:
1
docker build -t my-app:$IMAGE_TAG .
Then:
1
docker push my-registry/my-app:$IMAGE_TAG
And finally the deployment system pulls that exact image.
No:
“It works on my laptop but production is acting weird.”
At least, hopefully.
CI/CD doesn't eliminate bugs.
It just helps eliminate manual randomness.

Then I discovered secrets

Of course, you can't just put AWS credentials inside your repository.
So now you're dealing with:
  • GitHub Secrets
  • IAM roles
  • OIDC
  • environment variables
  • deployment credentials
And this is where CI/CD starts becoming more than just:
“Run these commands automatically.”
You're also designing a secure path from your source code to your infrastructure.
For AWS deployments, using GitHub's OIDC integration can allow workflows to assume an IAM role without storing long-lived AWS access keys in GitHub.
That was one of those things that made me think:
Okay, this is actually pretty clever.

The first time a pipeline fails

And then…
You push your code.
The pipeline starts.
Everything looks good.
Then:
FAILED
You open the logs.
Something about a missing environment variable.
You fix it.
Push again.
Now the Docker build fails.
Fix that.
Push again.
Now the deployment fails.
At some point you realize something important:
CI/CD isn't about making deployments boring.
It's about making the process predictable enough that when something goes wrong, you can actually figure out what went wrong.

The real goal

A good pipeline should make this:
1
“Can someone deploy this?”
into:
1
“Push the code and let the system handle it.”
But there's an even bigger goal.
You want deployments to become:
repeatable.
observable.
secure.
automated.
And ideally…
boring.
Because when it comes to production deployments, boring is actually a compliment.
If deploying version 1.4.2 is the exact same process as deploying version 1.4.1, that's a good thing.
You don't want your deployment process to depend on Dave remembering the secret command he ran six months ago.

Where I'm at now

The more I work with CI/CD, the more I realize it's basically the glue connecting everything else I've been learning.
GitHub gives you the code.
Docker packages the application.
A registry stores the image.
Terraform builds the infrastructure.
Kubernetes runs the workloads.
AWS provides the cloud.
And CI/CD connects all of these pieces into an automated workflow.
That's when DevOps started feeling less like a list of technologies to memorize and more like an actual system.
And honestly?
I'd still rather watch a pipeline deploy my application than SSH into a server and type commands manually.
My keyboard has suffered enough.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article