Deploy Dockerized Apps Using Docker-Setup: A Practical Guide

Deploy Dockerized Apps Using Docker-Setup: A Practical Guide

After setting up your server with docker-setup, you have a powerful environment ready for hosting applications. The setup provides Traefik for routing and SSL, Portainer for management, and Watchtower for automatic updates. Let's explore how to deploy applications in this environment.

Understanding Docker-Setup's Architecture

Docker-setup creates a streamlined environment where three core services work together to handle your applications. Traefik sits at the edge, managing incoming traffic and SSL certificates. Portainer provides an intuitive web interface for deployment management, while Watchtower keeps your containers updated automatically.

All services connect through a single network called traefik_network. This network allows Traefik to route traffic to your applications while providing necessary isolation between containers. When we deploy new applications, they'll need to join this network to be accessible through Traefik.

Preparing Your Application

To deploy an application successfully, you'll need a docker-compose.yml file with specific Traefik labels. Here's a practical example deploying a web application:

version: '3'

services:
  webapp:
    image: nginx
    container_name: my-webapp
    networks:
      - traefik_network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.webapp.rule=Host(`webapp.yourdomain.com`)"
      - "traefik.http.routers.webapp.entrypoints=websecure"
      - "traefik.http.routers.webapp.tls.certresolver=letsencrypt"
      # If your app doesn't use port 80 internally, specify the port:
      - "traefik.http.services.webapp.loadbalancer.server.port=8080"

networks:
  traefik_network:
    external: true

Let's understand these Traefik labels. The traefik.enable=true label tells Traefik to manage this container. The rule label defines how traffic reaches your app using the domain name you specify. The entrypoints label ensures HTTPS access, while the certresolver enables automatic SSL certificate management through Let's Encrypt.

Deployment Methods

Method 1: Using Portainer's Web Interface

Portainer provides a user-friendly way to deploy applications:

  1. Access your Portainer instance at portainer.yourdomain.com or http://<your-ip>:9000

  2. Navigate to "Stacks" in the left sidebar

  3. Click "Add stack"

  4. Name your stack (e.g., "webapp")

  5. Paste your docker-compose.yml content

  6. Click "Deploy the stack"

Method 2: Using Command Line

For those who prefer terminal access:

# Create a directory for your application
mkdir -p ~/apps/webapp
cd ~/apps/webapp

# Create docker-compose.yml with your preferred editor
nano docker-compose.yml

# Deploy the stack
docker compose up -d

Advanced Configuration Examples

Example 1: Multi-Container Application with Database

Here's how to deploy a web application with a database, ensuring proper communication between services:

version: '3'

services:
  webapp:
    image: your-web-app
    container_name: my-webapp
    networks:
      - traefik_network
      - backend
    environment:
      - DB_HOST=db
      - DB_PASSWORD_FILE=/run/secrets/db_password
    depends_on:
      - db
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.webapp.rule=Host(`webapp.yourdomain.com`)"
      - "traefik.http.routers.webapp.entrypoints=websecure"
      - "traefik.http.routers.webapp.tls.certresolver=letsencrypt"
    secrets:
      - db_password

  db:
    image: postgres:13
    container_name: my-webapp-db
    networks:
      - backend
    volumes:
      - db_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password

volumes:
  db_data:

networks:
  traefik_network:
    external: true
  backend:
    name: webapp_backend

secrets:
  db_password:
    file: ./db_password.txt

In this example, we create an additional internal network (backend) for secure database communication. Only the webapp container connects to both networks, while the database remains isolated from external access.

Example 2: Application with Multiple Subdomains

For applications requiring different subdomains:

version: '3'

services:
  frontend:
    image: your-frontend
    networks:
      - traefik_network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`app.yourdomain.com`)"
      - "traefik.http.routers.frontend.entrypoints=websecure"
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

  api:
    image: your-backend
    networks:
      - traefik_network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.yourdomain.com`)"
      - "traefik.http.routers.api.entrypoints=websecure"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"

networks:
  traefik_network:
    external: true

Monitoring Your Deployment

After deployment, you can monitor your application through several means:

  1. Portainer's dashboard shows container status and logs

  2. Traefik's dashboard displays routing and SSL certificate status

  3. Docker logs provide detailed container information:

# View container logs
docker logs my-webapp

# Follow logs in real-time
docker logs -f my-webapp

Common Issues and Solutions

  1. SSL Certificate Issues When SSL certificates fail to generate, first check your domain's DNS configuration. Ensure it points to your server's IP address and allow a few minutes for DNS propagation. You can verify Traefik's certificate generation process in its logs.

  2. Network Connectivity If containers can't communicate, verify they're properly connected to the traefik_network. For applications with databases, ensure your internal networks are correctly configured.

  3. Container Access When containers won't start, check their logs for startup errors. Verify environment variables are set correctly and all required volumes are properly mounted.

Best Practices

When deploying applications in this environment:

  1. Use specific image tags instead of 'latest' to ensure deployment consistency

  2. Implement health checks to monitor application status

  3. Store sensitive data using Docker secrets

  4. Regularly backup persistent data

  5. Monitor container resource usage through Portainer

This setup provides a robust foundation for deploying containerized applications. As you become more familiar with it, you can explore advanced Traefik features like rate limiting, middleware, and custom error pages to enhance your deployments.