Implement Docker network security with custom bridge networks and container isolation

Intermediate 25 min Jun 08, 2026 35 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Secure your Docker deployments by creating isolated custom bridge networks, implementing container segmentation, and configuring network access controls to prevent unauthorized communication between containers.

Prerequisites

  • Docker installed
  • Root or sudo access
  • Basic networking knowledge
  • Understanding of container concepts

What this solves

Docker's default bridge network allows all containers to communicate freely, creating security risks in multi-application environments. Custom bridge networks provide container isolation, network segmentation, and granular access controls to prevent data breaches and lateral movement attacks.

Docker network fundamentals and security risks

Docker's default networking model creates several security vulnerabilities. The default bridge network assigns containers to a shared subnet where they can communicate without restrictions. This means a compromised web application container could access your database container directly.

Custom bridge networks solve this by creating isolated network segments. Each network operates independently with its own subnet, and containers can only communicate within their assigned network unless explicitly configured otherwise.

Key security benefits: Network isolation prevents container-to-container attacks, reduces attack surface, and enables zero-trust networking principles in containerized environments.

Step-by-step implementation

Install Docker and verify network capabilities

First, ensure Docker is installed and check the current network configuration.

sudo apt update
sudo apt install -y docker.io docker-compose
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
sudo dnf install -y docker docker-compose
sudo systemctl enable --now docker
sudo usermod -aG docker $USER

Log out and back in for group changes to take effect, then verify Docker networks:

docker network ls
docker network inspect bridge

Create isolated custom bridge networks

Create separate networks for different application tiers. This example creates networks for web, application, and database layers.

# Create frontend network for web servers
docker network create --driver bridge \
  --subnet=172.20.1.0/24 \
  --gateway=172.20.1.1 \
  --opt com.docker.network.bridge.name=web-bridge \
  frontend-net

Create backend network for application servers

docker network create --driver bridge \ --subnet=172.20.2.0/24 \ --gateway=172.20.2.1 \ --opt com.docker.network.bridge.name=app-bridge \ backend-net

Create database network for data tier

docker network create --driver bridge \ --subnet=172.20.3.0/24 \ --gateway=172.20.3.1 \ --opt com.docker.network.bridge.name=db-bridge \ --opt com.docker.network.bridge.enable_icc=false \ database-net

Configure network access policies with iptables

Implement firewall rules to control traffic between network segments. These rules prevent unauthorized cross-network communication.

# Block inter-container communication on database network
sudo iptables -I DOCKER-USER -i db-bridge -o db-bridge -j DROP

Allow only backend network to access database network

sudo iptables -I DOCKER-USER -s 172.20.2.0/24 -d 172.20.3.0/24 -j ACCEPT

Allow only frontend to access backend on specific ports

sudo iptables -I DOCKER-USER -s 172.20.1.0/24 -d 172.20.2.0/24 -p tcp --dport 8080 -j ACCEPT

Block direct frontend to database access

sudo iptables -I DOCKER-USER -s 172.20.1.0/24 -d 172.20.3.0/24 -j DROP

Save iptables rules

sudo iptables-save > /etc/iptables/rules.v4

Create network policy enforcement script

Automate network security policy application with a reusable script.

#!/bin/bash

Docker Network Security Policy Script

set -euo pipefail echo "Applying Docker network security policies..."

Function to check if rule exists

rule_exists() { iptables -C DOCKER-USER "$@" 2>/dev/null }

Function to add rule if it doesn't exist

add_rule_if_not_exists() { if ! rule_exists "$@"; then iptables -I DOCKER-USER "$@" echo "Added rule: $@" else echo "Rule already exists: $@" fi }

Database network isolation

add_rule_if_not_exists -i db-bridge -o db-bridge -j DROP add_rule_if_not_exists -s 172.20.2.0/24 -d 172.20.3.0/24 -j ACCEPT

Frontend to backend communication (port 8080 only)

add_rule_if_not_exists -s 172.20.1.0/24 -d 172.20.2.0/24 -p tcp --dport 8080 -j ACCEPT

Block direct frontend to database

add_rule_if_not_exists -s 172.20.1.0/24 -d 172.20.3.0/24 -j DROP

Allow container health checks

add_rule_if_not_exists -p icmp --icmp-type echo-request -j ACCEPT echo "Network security policies applied successfully"

Log current rules for audit

iptables -L DOCKER-USER -n --line-numbers > /var/log/docker-network-rules.log echo "Rules logged to /var/log/docker-network-rules.log"
sudo chmod +x /opt/docker-network-security.sh
sudo /opt/docker-network-security.sh

Deploy containers to isolated networks

Launch containers in their designated network segments to test isolation.

version: '3.8'

services:
  web:
    image: nginx:alpine
    container_name: frontend-web
    networks:
      - frontend-net
    ports:
      - "80:80"
    environment:
      - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx/conf.d
    restart: unless-stopped

  app:
    image: node:alpine
    container_name: backend-app
    networks:
      - frontend-net
      - backend-net
    ports:
      - "8080:8080"
    working_dir: /app
    command: sh -c "echo 'const express = require(\"express\"); const app = express(); app.get(\"/health\", (req, res) => res.json({status: \"healthy\"})); app.listen(8080);' > server.js && npm init -y && npm install express && node server.js"
    restart: unless-stopped

  database:
    image: postgres:alpine
    container_name: backend-db
    networks:
      - database-net
      - backend-net
    environment:
      - POSTGRES_DB=appdb
      - POSTGRES_USER=appuser
      - POSTGRES_PASSWORD=securepassword123
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped

networks:
  frontend-net:
    external: true
  backend-net:
    external: true
  database-net:
    external: true

volumes:
  postgres_data:
docker-compose up -d

Configure container-level security policies

Add additional security constraints using Docker's built-in security options.

version: '3.8'

services:
  secure-web:
    image: nginx:alpine
    container_name: secure-frontend
    networks:
      - frontend-net
    security_opt:
      - no-new-privileges:true
      - apparmor:docker-default
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
    read_only: true
    tmpfs:
      - /tmp:size=100M,noexec,nosuid,nodev
      - /var/cache/nginx:size=50M,noexec,nosuid,nodev
      - /var/run:size=10M,noexec,nosuid,nodev
    user: "101:101"
    restart: unless-stopped

  secure-app:
    image: node:alpine
    container_name: secure-backend
    networks:
      - backend-net
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - SETGID
      - SETUID
    user: "1001:1001"
    restart: unless-stopped

networks:
  frontend-net:
    external: true
  backend-net:
    external: true

Set up network monitoring and audit logging

Configure logging to monitor network traffic and detect security violations.

# Docker network security logging
:msg, contains, "DOCKER-USER" /var/log/docker-network-security.log
& stop
sudo systemctl restart rsyslog

Add logging to iptables rules

sudo iptables -I DOCKER-USER -s 172.20.1.0/24 -d 172.20.3.0/24 -j LOG --log-prefix "DOCKER-SECURITY-VIOLATION: " sudo iptables -I DOCKER-USER -s 172.20.1.0/24 -d 172.20.3.0/24 -j DROP

Create network security monitoring script

Implement automated monitoring to detect and alert on security policy violations.

#!/bin/bash

Docker Network Security Monitor

SECURITY_LOG="/var/log/docker-network-security.log" ALERT_EMAIL="admin@example.com" LOGFILE="/var/log/docker-security-monitor.log" log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOGFILE" } check_violations() { local violations violations=$(grep -c "DOCKER-SECURITY-VIOLATION" "$SECURITY_LOG" 2>/dev/null || echo 0) if [ "$violations" -gt 0 ]; then log_message "ALERT: $violations network security violations detected" # Get recent violations tail -n 20 "$SECURITY_LOG" | grep "DOCKER-SECURITY-VIOLATION" > /tmp/recent_violations.txt # Send alert email if mail is configured if command -v mail >/dev/null 2>&1; then mail -s "Docker Network Security Alert" "$ALERT_EMAIL" < /tmp/recent_violations.txt fi return 1 fi return 0 } check_network_health() { local networks networks=("frontend-net" "backend-net" "database-net") for network in "${networks[@]}"; do if ! docker network inspect "$network" >/dev/null 2>&1; then log_message "ERROR: Network $network is missing" return 1 fi done log_message "All networks are healthy" return 0 }

Main monitoring loop

log_message "Starting Docker network security monitoring" while true; do check_violations check_network_health # Check every 5 minutes sleep 300 done
sudo chmod +x /opt/monitor-docker-security.sh

Create systemd service for monitoring

sudo tee /etc/systemd/system/docker-security-monitor.service > /dev/null << 'EOF' [Unit] Description=Docker Network Security Monitor After=docker.service Requires=docker.service [Service] Type=simple ExecStart=/opt/monitor-docker-security.sh Restart=always RestartSec=30 User=root [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now docker-security-monitor

Monitor and audit network security

Set up Prometheus monitoring integration

Configure metrics collection for network security monitoring using Docker's built-in metrics and custom exporters.

version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: docker-prometheus
    networks:
      - monitoring-net
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.enable-lifecycle'
    restart: unless-stopped

  node-exporter:
    image: prom/node-exporter:latest
    container_name: docker-node-exporter
    networks:
      - monitoring-net
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    restart: unless-stopped

networks:
  monitoring-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.4.0/24

volumes:
  prometheus_data:
global:
  scrape_interval: 30s
  evaluation_interval: 30s

scrape_configs:
  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']
    metrics_path: /metrics
    scrape_interval: 30s
    
  - job_name: 'docker-security'
    static_configs:
      - targets: ['host.docker.internal:9323']
    metrics_path: /metrics
# Create monitoring network
docker network create --driver bridge --subnet=172.20.4.0/24 monitoring-net

Deploy monitoring stack

docker-compose -f docker-monitoring.yml up -d

For more advanced monitoring setups, check out our guide on monitoring Docker containers with Prometheus and Grafana.

Verify your setup

Test network isolation and security policies to ensure proper configuration.

# Check network isolation
docker exec frontend-web ping -c 3 backend-db

Should fail - no route to database network

Test allowed communication

docker exec frontend-web curl -f http://backend-app:8080/health

Should succeed - frontend can reach backend

Verify iptables rules

sudo iptables -L DOCKER-USER -n --line-numbers

Check security violations log

sudo tail -f /var/log/docker-network-security.log

Verify network configuration

docker network ls docker network inspect frontend-net backend-net database-net

Check container security settings

docker inspect secure-frontend | grep -A 10 "SecurityOpt"

Monitor network traffic

sudo netstat -i sudo ss -tulpn | grep docker
Testing tip: Use docker exec -it container_name /bin/sh to get shell access and test network connectivity between containers manually.

Common issues

Symptom Cause Fix
Containers can't communicate Not on same network Add container to required network with docker network connect
iptables rules not applied Docker daemon restart cleared rules Add rules to startup script or use iptables-persistent
Network creation fails Subnet conflict with existing networks Choose different subnet range with docker network ls
Container health checks fail ICMP blocked by iptables Add rule: iptables -I DOCKER-USER -p icmp -j ACCEPT
Web app can't reach database App container not on backend network Connect to both frontend and backend networks
Security violations not logged Rsyslog not configured Restart rsyslog: sudo systemctl restart rsyslog
Never use --network=host in production. This bypasses all Docker networking security and exposes containers directly to the host network, eliminating isolation benefits.

Advanced security configurations

For production environments, consider implementing additional security layers:

  • Use Docker Secrets for sensitive data instead of environment variables
  • Implement container runtime security with Falco for threat detection
  • Configure image security scanning with vulnerability assessment tools
  • Set up network policies in Kubernetes for orchestrated environments
  • Implement zero-trust networking with service mesh technologies

For Kubernetes environments, explore implementing Kubernetes network policies for similar security benefits at the orchestration layer.

Next steps

Running this in production?

Want this handled for you? Setting this up once is straightforward. Keeping it patched, monitored, backed up and performant across environments is the harder part. See how we run infrastructure like this for European teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle infrastructure security hardening for businesses that depend on uptime. From initial setup to ongoing operations.