Running Multiple Docker Minecraft Containers on the same host
I needed to do this obviously to appease my son who needs various servers running. The spec was one creative and one survival server and I don't want to run in a VM since running itzg/minecraft-bedrock-server:latest image has been great for the single Minecraft bedrock server. This also means I can tinker with various Minecraft java images without stopping the existing container which is handy. Normally you can't do this, since the listening port 19132 can only be bound to a single container, and if you try to port map it in docker config, it won't connect from Windows clients.
I run all my docker containers from a single docker-compose.yaml, but you can manage it however you like. The essential bits are:
Set up a macvlan network for docker - this more or less allows you to assign static IPs to your containers. Bridge it with your existing ethernet connection in your docker-compose file, in my case the catchy-named enp1s0.
networks:
macvlan:
driver: macvlan
driver_opts:
parent: enp1s0
macvlan_mode: bridge
ipam:
driver: default
config:
- subnet: 192.168.0.0/24
Set up your 2 containers with static IP addresses. You'll want to set something outside the dynamic IP allocation range (the range assigned via DHCP), which you should be able to find in your router or whatever dishes out IP addresses. This would also go in your docker-compose file under services:
minecraft-bedrock:
image: itzg/minecraft-bedrock-server:latest
container_name: minecraft-bigsteve-creative
labels:
com.centurylinklabs.watchtower.enable: true
environment:
PUID: 1001
PGID: 1001
EULA: "TRUE"
GAMEMODE: creative
DIFFICULTY: easy
SERVER_NAME: "BigSteve!"
MAX_PLAYERS: 8
MAX_THREADS: 4
ALLOW_CHEATS: "false"
ALLOW_LIST_USERS: "List of UserIds"
ALLOW_LIST: "false"
DEFAULT_PLAYER_PERMISSION_LEVEL: operator
VERSION: LATEST
TZ: Europe/London
LEVEL_NAME: "BigSteveCreative"
ports:
- "19132:19132/udp"
volumes:
- /mnt/minecraft-bedrock/data:/data
stdin_open: true
tty: true
restart: unless-stopped
networks:
macvlan:
ipv4_address: 192.168.0.250
minecraft-2024-survival:
image: itzg/minecraft-bedrock-server:latest
container_name: minecraft-2024-survival
labels:
com.centurylinklabs.watchtower.enable: true
environment:
PUID: 1001
PGID: 1001
EULA: "TRUE"
GAMEMODE: survival
DIFFICULTY: easy
SERVER_NAME: "2024-Survival"
MAX_PLAYERS: 8
MAX_THREADS: 4
ALLOW_CHEATS: "false"
ALLOW_LIST_USERS: ALLOW_LIST_USERS: "List of UserIds"
ALLOW_LIST: "false"
DEFAULT_PLAYER_PERMISSION_LEVEL: operator
VERSION: LATEST
TZ: Europe/London
LEVEL_NAME: "2024-Survival"
ports:
- "19132:19132/udp"
volumes:
- /mnt/minecraft-2024-survival/data:/data
stdin_open: true
tty: true
restart: unless-stopped
networks:
macvlan:
ipv4_address: 192.168.0.251
Setup a systemd service to ip link a mac0 interface to the ethernet, with type of macvlan, mode bridge. This means the interface should be available at boot with no further action required.
sudo vim /etc/systemd/system/macvlan-setup.service
(start of file)
[Unit]
Description=Configure macvlan interface
After=network.target
[Service]
Type=oneshot
ExecStart=/sbin/ip link add mac0 link enp1s0 type macvlan mode bridge
ExecStart=/sbin/ip addr add 192.168.0.0/24 dev mac0
ExecStart=/sbin/ip link set mac0 up
RemainAfterExit=yes
ExecStop=/sbin/ip link delete mac0
StandardOutput=journal
[Install]
WantedBy=multi-user.target
(end of file)
Then other systemd stuff
sudo chmod 644 /etc/systemd/system/macvlan-setup.service
sudo systemctl enable macvlan-setup
sudo systemctl status macvlan-setup
ip link show mac0
(output...)
149: mac0@enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 32:15:e5:aa:fa:2e brd ff:ff:ff:ff:ff:ff
And finally, update your containers from docker-compose.
docker compose -f ~/docker/docker-compose.yml up
At this point you should be good, able to join from other Windows machines on the network to either container without issue.