2025-03-30 | Modern Full-Stack Development with TypeScript (Cont.)
Introduction
This seminar is the final part of our Modern Full-Stack Development with TypeScript series.
Part 8: Deploy Docker using Ansible (25 minutes)
Ansible Overview
Ansible is an open-source automation tool that simplifies application deployment, configuration management, and task automation.
Key benefits:
- Agentless architecture (only requires SSH)
- YAML-based playbooks for easy readability
- Idempotent operations (safe to run multiple times)
- Extensive module library
- Infrastructure as Code approach
Why Ansible for Docker Deployment?
- Consistency: Ensure identical deployments across environments
- Automation: Reduce manual steps and human error
- Scalability: Easily deploy to multiple servers
- Orchestration: Coordinate complex deployment sequences
- Configuration Management: Handle environment-specific settings
Setting Up Ansible
# inventory.yml
all:
hosts:
production:
ansible_host: 192.168.1.100
ansible_user: deploy
staging:
ansible_host: 192.168.1.101
ansible_user: deploy
vars:
ansible_python_interpreter: /usr/bin/python3
Creating an Ansible Playbook for Docker Deployment
# deploy-docker.yml
---
- name: Deploy Application with Docker
hosts: all
become: true
vars:
app_name: fullstack-app
docker_compose_dir: /opt/{{ app_name }}
env: "{{ lookup('env', 'DEPLOY_ENV') | default('staging', true) }}"
tasks:
- name: Install required packages
apt:
name:
- docker.io
- docker-compose
- python3-pip
state: present
update_cache: yes
- name: Ensure Docker service is running
service:
name: docker
state: started
enabled: yes
- name: Create application directory
file:
path: "{{ docker_compose_dir }}"
state: directory
mode: '0755'
- name: Copy docker-compose file
template:
src: templates/docker-compose.{{ env }}.yml.j2
dest: "{{ docker_compose_dir }}/docker-compose.yml"
- name: Copy environment variables
template:
src: templates/.env.{{ env }}.j2
dest: "{{ docker_compose_dir }}/.env"
mode: '0600'
- name: Pull latest Docker images
command:
cmd: docker-compose pull
chdir: "{{ docker_compose_dir }}"
- name: Deploy with docker-compose
command:
cmd: docker-compose up -d
chdir: "{{ docker_compose_dir }}"
- name: Prune unused Docker images
command: docker image prune -af
register: prune_result
changed_when: "'Total reclaimed space:' in prune_result.stdout"
Environment-Specific Configuration Templates
# templates/docker-compose.production.yml.j2
version: '3.8'
services:
api:
image: {{ docker_registry }}/{{ app_name }}-api:{{ api_version }}
restart: always
ports:
- "3000:3000"
environment:
NODE_ENV: production
DATABASE_URL: ${DATABASE_URL}
JWT_SECRET: ${JWT_SECRET}
depends_on:
- postgres
networks:
- app-network
deploy:
replicas: 2
update_config:
parallelism: 1
delay: 10s
client:
image: {{ docker_registry }}/{{ app_name }}-client:{{ client_version }}
restart: always
ports:
- "80:80"
depends_on:
- api
networks:
- app-network
postgres:
image: postgres:14
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USER}
POSTGRES_DB: ${DB_NAME}
networks:
- app-network
restart: always
networks:
app-network:
driver: bridge
volumes:
postgres-data:
driver: local
Ansible Roles for Reusable Components
Organize your Ansible code into roles for better maintainability:
roles/
├── docker/
│ ├── tasks/
│ │ └── main.yml
│ └── handlers/
│ └── main.yml
├── nginx/
│ ├── tasks/
│ │ └── main.yml
│ ├── templates/
│ │ └── nginx.conf.j2
│ └── handlers/
│ └── main.yml
└── app/
├── tasks/
│ └── main.yml
├── templates/
│ ├── docker-compose.yml.j2
│ └── .env.j2
└── defaults/
└── main.yml
Continuous Deployment with Ansible and CI/CD
# .github/workflows/deploy.yml
name: Deploy Application
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Ansible
run: |
python -m pip install --upgrade pip
pip install ansible
- name: Set up SSH key
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }}
- name: Run Ansible playbook
run: |
ansible-playbook -i inventory.yml deploy-docker.yml
env:
DEPLOY_ENV: production
ANSIBLE_HOST_KEY_CHECKING: False
Best Practices for Ansible Deployments
Vault for Secrets: Use Ansible Vault to encrypt sensitive data
ansible-vault create secrets.yml ansible-playbook deploy.yml --ask-vault-passDynamic Inventories: Use cloud provider plugins for dynamic server discovery
Idempotency: Ensure playbooks can be run multiple times without side effects
Tags: Use tags to run specific parts of your playbook
ansible-playbook deploy.yml --tags "update,restart"Handlers: Use handlers for actions that should only run when a change occurs
Testing: Test playbooks with Molecule before production deployment
Monitoring and Maintenance
- Set up regular health checks using Ansible
- Create playbooks for common maintenance tasks:
- Database backups
- Log rotation
- Certificate renewal
- Security updates
Rollback Strategies
# rollback.yml
---
- name: Rollback to previous version
hosts: all
become: true
vars:
app_name: fullstack-app
docker_compose_dir: /opt/{{ app_name }}
previous_version: "{{ lookup('env', 'PREVIOUS_VERSION') }}"
tasks:
- name: Update docker-compose with previous version
lineinfile:
path: "{{ docker_compose_dir }}/docker-compose.yml"
regexp: "image: .*/{{ app_name }}-api:.*"
line: " image: {{ docker_registry }}/{{ app_name }}-api:{{ previous_version }}"
- name: Restart with previous version
command:
cmd: docker-compose up -d
chdir: "{{ docker_compose_dir }}"
Conclusion and Next Steps (15 minutes)
Summary of the Full-Stack TypeScript Journey
- Angular for dynamic frontend experiences
- Nest.js for structured backend development
- PostgreSQL and Prisma for type-safe data management
- Swagger for API documentation
- Docker for containerization
- Ansible for automated deployment
Emerging Trends and Future Directions
- Serverless architectures
- Edge computing
- WebAssembly
- Micro-frontends
- GraphQL adoption
- AI-assisted development
Continuous Learning Resources
- Community forums and Discord servers
- Advanced courses and certifications
- Open-source contribution opportunities
- Tech conferences and meetups
Q&A Session
Open floor for questions about any aspect of the full-stack TypeScript ecosystem we’ve covered throughout this seminar series.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.