Skip to main content

Docker

This document describes how to deploy (IPv4 and IPv6) StackV using Docker and how to verify connectivity. It also includes notes for troubleshooting Docker's IPv6 limitations.

Installing Docker

  • sudo yum install -y docker (or use your distro's package manager)

  • sudo systemctl enable docker && sudo systemctl start docker

IPv4 Deployment

TODO

IPv6 Deployment

Docker Host Configuration for IPv6

For Docker containers to communicate over IPv6, the Docker daemon must be configured to manage an IPv6 subnet.

  1. Edit the Docker Daemon Configuration File:

    Open or create the file /etc/docker/daemon.json. Add the following configuration to enable IPv6 and assign a default address pool for Docker networks.

    {
    "ipv6": true,
    "fixed-cidr-v6": "2001:db8:21::/64"
    }

    Note: 2001:db8::/32 is a prefix reserved for documentation. For production, it is recommended to use a Unique Local Address (ULA) prefix from your organization's assigned block.

  2. Apply the Configuration

    Restart the Docker service for the changes to take effect.

    sudo systemctl restart docker

StackV Deployment with docker-compose.yml

The following docker-compose.yml defines the app and db services for StackV, configured within an IPv6-enabled network.

docker-compose.yml

version: '3.7'
services:
app:
image: virnao/stackv-orchestrator:release-r2025.1.1
command: ['/bin/wait-for-it.sh', 'db:3306', '-t', '600', '-s', '--', 'sh', '-c', '/bin/startup.sh']
depends_on:
- db
environment:
KC_DOMAIN: <YOUR_HOSTNAME_OR_DOMAIN>:<APP_PORT>
KC_CLIENT: StackV
KC_SECRET: <SECRET_VALUE>
TLS_PASS: password
MAIL_PORT: 587
MAIL_HOST: smtp.office365.com
MAIL_USER: no.reply.stackv@outlook.com
MAIL_PASS: password
JAVA_MEMORY: 24G
healthcheck:
start_period: 60s
test: ['CMD', 'curl', '-f', '-k', 'https://0.0.0.0:<APP_PORT>/StackV-web/portal/']
retries: 5
ports:
- "8443:8443/tcp"
- "[::]:8443:8443/tcp"
restart: always
volumes:
- db_data:/var/lib/mysql
- /opt/stackv/tls:/opt/jboss/wildfly/standalone/configuration/tls
networks:
- stackv-net

db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: stackdbpass
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '-uroot', '-pstackdbpass']
restart: always
volumes:
- db_data:/var/lib/mysql
- /opt/stackv/db/bin/localhost.sql:/docker-entrypoint-initdb.d/localhost.sql:ro
- /opt/stackv/db/bin/postprocess.sql:/docker-entrypoint-initdb.d/postprocess.sql:ro
- /opt/stackv/db/config:/etc/mysql/conf.d
networks:
- stackv-net

volumes:
db_data:

networks:
stackv-net:
driver: bridge
enable_ipv6: true
ipam:
config:
- subnet: 10.0.21.0/24
- subnet: "<DOCKER_IPV6_PREFIX>/64"

Note on IPv6 Addressing:

  • Replace DOCKER_IPV6_PREFIX with your chosen Docker IPv6 network prefix.
  • The host machine should have a public/global IPv6 address (e.g., HOST_IPV6) that is used for publishing ports.

To deploy StackV:

  • Save the content above as docker-compose.yml, replace placeholder values (like YOUR_HOSTNAME_OR_DOMAIN), and run:

    docker-compose up -d

Verifying Bidirectional IPv6 Connectivity

Verification is a two-part process to confirm traffic can flow in both directions.

Part A: Outbound Verification (Client \u2192 StackV Server)

This tests if you can reach the containerized service from an external machine (e.g., your laptop).

  1. Check Local Machine's IPv6 Connectivity:

    Get your public IPv6 address

    • curl -6 -s https://v6.ident.me
  2. Resolve the Server's IPv6 Address:

    Confirm the AAAA DNS record points to the host's IPv6

    • dig AAAA <YOUR_HOSTNAME_OR_DOMAIN> +short
  3. Test Network and Port Reachability:

    Ping the host machine

    • ping -6 <HOST_IPV6>

    Check if the application port (8443) is open

    • nc -6vz <HOST_IPV6> <APP_PORT>
  4. Test the Application Service:

    Connect to the application using its hostname

    • curl -6 -v -k https://<YOUR_HOSTNAME_OR_DOMAIN>:<APP_PORT>/StackV-web/portal/

    Or, connect directly using the host's IPv6 address (note the brackets)

    • curl -6 -v -k "https://[<HOST_IPV6>]:<APP_PORT>/yourapp/portal/"

Part B: Inbound Verification (StackV Server \u2192 Client)

This crucial test confirms the return path is clear by having the remote server connect back to a service running on your local machine.

  1. Prepare Your Local Machine:

    • Find your current global IPv6 address: curl -6 https://v6.ident.me/
    • Ensure your local firewall is not blocking incoming traffic on test ports (e.g., 44444, 8080).
  2. Set Up Test Listeners on Your Local Machine:

    • Option 1: Simple TCP Listener with ncat

      On your local machine, listen on port 44444 for any IPv6 connection

      • sudo ncat -6 -l -p 44444 --keep-open

      Verify with:

      • ss -lntp | grep 44444
    • Option 2: HTTP Server with Docker (nginx)

      Run a temporary nginx container publishing port 8080 on IPv6

      • docker run -d --name test-nginx -p "[::]:8080:80" nginx:alpine

      Verify it is listening on [::]:8080

      • ss -lntp | grep 8080
  3. Execute the Test from the Remote Server:

    • SSH into the remote server where StackV is running.
    • Use your local machine's IPv6 address (LOCAL_IPV6) found in step 1.

    Test the ncat listener

    • nc -6vz [<LOCAL_IPV6>] 44444

    Test the nginx HTTP server

    • curl -6 -v http://[<LOCAL_IPV6>]:8080

    Expected results: nc should report "Connection succeeded", and curl should return the "Welcome to nginx!" HTML page. If these tests time out, proceed to troubleshooting.

Troubleshooting Common Issues

  • Issue: Inbound Tests Fail (Timeout)

    • Cause: This is often due to asymmetric routing, especially if your local machine is on a VPN. The server's connection request (SYN) arrives via your Wi-Fi/Ethernet, but your machine's reply (SYN-ACK) is incorrectly routed out through the VPN, breaking the handshake.

    • Diagnosis: On your local machine, use tcpdump to watch for incoming packets: sudo tcpdump -i any -n 'host REMOTE_HOST_IPV6 and port TEST_PORT'. If you see a SYN packet arrive but no reply is sent from your physical interface, asymmetric routing is the likely cause.

    • Solution: Add a specific route on your local machine to force replies to the server to bypass the VPN. Find your default gateway (ip -6 route | grep default) and add the route:

      • sudo ip -6 route add <REMOTE_HOST_IPV6> via <your_gateway_link_local_address> dev <your_physical_interface
  • Issue: Service is Not Listening on IPv6

    • Cause: Docker did not bind the port to the host's IPv6 address.

    • Diagnosis: On the remote host, run ss -lntp | grep APP_PORT. The output must show a listener on [::]:APP_PORT or :::APP_PORT. If it only shows 0.0.0.0:APP_PORT, it is only listening on IPv4.

    • Solution: Ensure your docker-compose.yml uses the [::]:<HOST_PORT>:<CONTAINER_PORT> syntax in the ports section. This explicitly tells Docker to create an IPv6 binding.