Skip to content
MikroTik RouterOS Docs

Container (Docker) Basic Setup on MikroTik RouterOS

RouterOS Version: 7.4+ Difficulty: Intermediate Estimated Time: 30 minutes

For the impatient: here’s the 30-second version.

# Minimal container setup (requires container mode enabled first)
/interface/veth/add name=veth1 address=172.17.0.2/24 gateway=172.17.0.1
/interface/bridge/add name=containers
/ip/address/add address=172.17.0.1/24 interface=containers
/interface/bridge/port add bridge=containers interface=veth1
/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.17.0.0/24
/container/add remote-image=nginx interface=veth1 root-dir=disk1/images/nginx

MikroTik’s Container feature brings Docker-compatible containerization to RouterOS, enabling you to run applications like Pi-hole, Home Assistant, or custom services directly on your router. This transforms your MikroTik device from a simple network appliance into a versatile edge computing platform.

Understanding containers on RouterOS requires grasping two key concepts: the security model (why physical access is required) and the networking model (how containers connect to your network). This guide covers the essential setup process and demonstrates a minimal working example.

RouterOS containers run with significant system privileges, which creates both opportunities and risks:

Why Physical Access is Required:

  • Container mode must be explicitly enabled via device-mode
  • This prevents remote attackers from enabling containers without physical access
  • Once enabled, containers can be managed remotely (both benefit and risk)

Security Implications:

  • Containers can potentially access RouterOS internals
  • Malicious container images could compromise your entire router
  • Your router’s security becomes equivalent to the least secure container you run
  • Expert attackers can potentially achieve root access and install persistent backdoors

Best Practices:

  • Only run containers from trusted sources
  • Use external storage to limit internal flash wear
  • Monitor container resource usage
  • Keep RouterOS updated
  • Consider dedicated hardware for untrusted containers

RouterOS containers use a unique networking approach that differs from standard Docker:

Container Networking Architecture

Key Components:

  • VETH Interface: Virtual Ethernet pair connecting RouterOS to container
  • Container Bridge: RouterOS bridge providing container networking
  • NAT Rules: Enable container internet access and port forwarding
  • Container Namespace: Isolated network environment for the application
  • RouterOS 7.4+ with Container package installed
  • Physical access to the device (for initial container mode enable)
  • External storage (USB/SATA/NVMe) with 100MB/s+ speed recommended
  • At least 512MB RAM (more for complex applications)
  • Understanding of basic RouterOS networking concepts
  • Container mode enabled (see below)

Hardware Limitations:

  • ARM, ARM64, and x86 architectures supported
  • EN7562CT CPU devices (hEX Refresh) limited to arm32v5 images only
  • 16MB SPI flash devices require external storage for images

Container support is disabled by default and requires physical confirmation for security. Run this command and follow the physical confirmation process:

/system/device-mode/update container=yes

This will prompt you to either press the reset button or perform a cold reboot to confirm. This security measure prevents remote attackers from enabling containers without physical access. Once enabled, container mode persists across reboots and you only need to do this once.

Set up the virtual networking that containers will use:

/interface/veth/add name=veth1 address=172.17.0.2/24 gateway=172.17.0.1
/interface/bridge/add name=containers
/ip/address/add address=172.17.0.1/24 interface=containers
/interface/bridge/port add bridge=containers interface=veth1

Enable NAT so containers can reach the internet:

/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.17.0.0/24

Deploy a simple nginx web server to verify the setup works:

/container/config/set registry-url=https://registry-1.docker.io tmpdir=disk1/tmp
/container/add remote-image=nginx interface=veth1 root-dir=disk1/images/nginx name=test-nginx start-on-boot=yes logging=yes

Note: Container commands require container mode to be enabled (see Prerequisites). If you haven’t enabled container mode yet, these commands will fail with an error.

Confirm your container setup is working correctly:

/container/print

Expected Output:

Flags: X - DISABLED, R - RUNNING
0 R name="test-nginx" tag="nginx:latest" os="linux" arch="arm64" interface=veth1
root-dir=disk1/images/nginx mounts="" dns="" logging=yes start-on-boot=yes
status=running
/ping 172.17.0.2 count=3

Expected Output:

SEQ HOST SIZE TTL TIME STATUS
0 172.17.0.2 56 64 0ms
1 172.17.0.2 56 64 0ms
2 172.17.0.2 56 64 0ms
sent=3 received=3 packet-loss=0% min-rtt=0ms avg-rtt=0ms max-rtt=0ms
/container/shell test-nginx cmd="ping -c 3 8.8.8.8"

Expected Output:

PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=118 time=10.123 ms
64 bytes from 8.8.8.8: seq=1 ttl=118 time=9.456 ms
64 bytes from 8.8.8.8: seq=2 ttl=118 time=8.789 ms

Container storage in RouterOS involves several directory types:

Root Directory (root-dir):

  • Contains the extracted container image filesystem
  • Should be on external storage for performance
  • Example: disk1/images/nginx

Temporary Directory (tmpdir):

  • Used during image download and extraction
  • Can be on external storage to save internal flash
  • Example: disk1/tmp

Mount Points:

  • Persistent data volumes that survive container restarts
  • Critical for databases, configuration files, logs
  • Example: disk1/volumes/nginx/html → /usr/share/nginx/html

Storage Performance Requirements:

  • Minimum 100MB/s sequential read/write
  • 10K random IOPS recommended
  • Use /disk/test to verify performance
  • USB 3.0+ or SATA/NVMe preferred over USB 2.0
# Start a container
/container/start test-nginx
# Stop a container
/container/stop test-nginx
# Restart a container
/container/stop test-nginx
/container/start test-nginx
# Interactive shell access
/container/shell test-nginx
# Execute single command
/container/shell test-nginx cmd="ls -la /etc"
# Execute as specific user
/container/shell test-nginx user=www-data cmd="whoami"
# View container status and resource usage
/container/print detail
# Monitor logs (if logging=yes)
/log/print where topics~"container"
Section titled “Pattern 1: Bridge with NAT (Recommended for Most Use Cases)”

This is the default pattern shown in the configuration steps above. Containers share a private network with NAT for internet access.

Advantages:

  • Simple to configure
  • Secure (containers not directly accessible)
  • Multiple containers can share the same network

Use Cases:

  • Web applications with port forwarding
  • Internal services (databases, caches)
  • Development and testing

Container shares the host’s network namespace directly:

/interface/veth/add name=veth-host address=192.168.88.10/24 gateway=192.168.88.1
/interface/bridge/port add bridge=bridge interface=veth-host

Advantages:

  • Better network performance
  • No port forwarding needed
  • Container appears as another device on LAN

Disadvantages:

  • Less secure (all container ports exposed)
  • Potential port conflicts with RouterOS services
  • Only one container per port

Separate containers into different networks for security:

# Create isolated networks
/interface/veth/add name=veth-web address=172.18.0.2/24 gateway=172.18.0.1
/interface/veth/add name=veth-db address=172.19.0.2/24 gateway=172.19.0.1
/interface/bridge/add name=web-containers
/interface/bridge/add name=db-containers
# Configure addressing
/ip/address/add address=172.18.0.1/24 interface=web-containers
/ip/address/add address=172.19.0.1/24 interface=db-containers
# Add interfaces to bridges
/interface/bridge/port add bridge=web-containers interface=veth-web
/interface/bridge/port add bridge=db-containers interface=veth-db
# Configure NAT for both networks
/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.18.0.0/24
/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.19.0.0/24

Problem: Container fails to start with “extraction failed”

Section titled “Problem: Container fails to start with “extraction failed””

Symptoms: Container status shows “extracting” then “stopped” Causes:

  • Insufficient disk space
  • Slow storage performance
  • Corrupted image download
  • Architecture mismatch

Solutions:

  1. Check available disk space: /disk/print
  2. Test storage performance: /disk/test disk1
  3. Clear temporary files: /file/remove [find where name~"tmp"]
  4. Verify architecture compatibility
  5. Try a different container image

Symptoms: Container can’t reach external hosts Causes:

  • Missing NAT rule
  • Incorrect gateway configuration
  • DNS resolution issues
  • Firewall blocking traffic

Solutions:

  1. Verify NAT rule exists: /ip/firewall/nat/print
  2. Check container gateway: /interface/veth/print
  3. Test from RouterOS: /ping 8.8.8.8
  4. Check container DNS: /container/shell <name> cmd="nslookup google.com"

Symptoms: Web interface not reachable from LAN Causes:

  • Missing port forwarding rule
  • Container not listening on expected port
  • Firewall blocking access
  • Wrong container IP address

Solutions:

  1. Add port forwarding: /ip/firewall/nat/add chain=dstnat action=dst-nat dst-port=80 protocol=tcp to-addresses=172.17.0.2 to-ports=80
  2. Verify container is listening: /container/shell <name> cmd="netstat -ln"
  3. Check container IP: /container/print
  4. Test internal connectivity: /ping 172.17.0.2

Symptoms: Router becomes slow, out of memory errors Causes:

  • Container memory leak
  • Insufficient RAM for workload
  • Multiple containers competing for resources

Solutions:

  1. Set memory limits: /container/config/set memory-high=200M
  2. Monitor usage: /container/print detail
  3. Restart problematic containers
  4. Consider external hardware for resource-intensive applications

Symptoms: Slow container startup, application timeouts Causes:

  • Using internal flash storage
  • Slow USB 2.0 devices
  • Fragmented filesystem

Solutions:

  1. Move to external storage: USB 3.0+, SATA, or NVMe
  2. Test performance: /disk/test disk1
  3. Use faster filesystem: ext4 or btrfs
  4. Ensure adequate free space (>20% recommended)
  • Only use images from trusted registries
  • Verify image signatures when possible
  • Regularly update container images
  • Scan images for vulnerabilities before deployment
  • Use isolated networks for untrusted containers
  • Implement firewall rules to restrict container access
  • Avoid host networking mode unless necessary
  • Monitor container network traffic
  • Limit container privileges with user/group settings
  • Use read-only mounts where possible
  • Implement proper authentication for container services
  • Regular security audits of running containers
  • Use encrypted storage for sensitive data
  • Implement regular backups of container volumes
  • Secure container environment variables
  • Monitor container logs for suspicious activity
# Create environment variable lists
/container/envs/add list=ENV_NGINX key=NGINX_HOST value=example.com
/container/envs/add list=ENV_NGINX key=NGINX_PORT value=80
# Apply to container
/container/set test-nginx envlist=ENV_NGINX
# Create persistent storage mounts
/container/mounts/add name=MOUNT_NGINX_HTML src=disk1/volumes/nginx/html dst=/usr/share/nginx/html
/container/mounts/add name=MOUNT_NGINX_CONF src=disk1/volumes/nginx/conf dst=/etc/nginx
# Apply to container
/container/set test-nginx mounts=MOUNT_NGINX_HTML,MOUNT_NGINX_CONF
# Set CPU affinity (limit to specific cores)
/container/set test-nginx cpu-list=0,1
# Set memory limits
/container/set test-nginx memory-high=512M
# Configure restart behavior
/container/set test-nginx auto-restart-interval=30s
  • Resources - monitor container resource usage
  • Files - container storage management