Problems with Docker Compose setup and Minecraft Example

Hello, I am having a bit of trouble using the Docker Compose setup.

I’m trying to deploy the compose stack on a public Oracle Cloud Instance, for which I followed this tutorial. The OCL firewall configuration looks as follows

I first tried with some custom services but since I had some trouble I decided to try to replicate the Minecraft Tutorial since that worked for me when I tried the non-docker-compose setup, but I’m still having issues.

Im using the following docker-compose.yml. I took this example and made a couple modifications: i updated compose version to 3.9 and I reduced the networks to just one since this is deployed on a public machine with no other containers)

version: '3.9'
services:

  ziti-controller:
    image: "${ZITI_IMAGE}:${ZITI_VERSION}"
    env_file:
      - ./.env
    ports:
      - ${ZITI_EDGE_CONTROLLER_PORT:-1280}:${ZITI_EDGE_CONTROLLER_PORT:-1280}
      - ${ZITI_CTRL_PORT:-6262}:${ZITI_CTRL_PORT:-6262}
    environment:
      - ZITI_EDGE_IDENTITY_ENROLLMENT_DURATION=${ZITI_EDGE_IDENTITY_ENROLLMENT_DURATION}
      - ZITI_EDGE_ROUTER_ENROLLMENT_DURATION=${ZITI_EDGE_ROUTER_ENROLLMENT_DURATION}
    networks:
      ziti:
        aliases:
          - ziti-edge-controller
    volumes:
      - ziti-fs:/persistent
    entrypoint:
      - "/var/openziti/scripts/run-controller.sh"

  ziti-controller-init-container:
    image: "${ZITI_IMAGE}:${ZITI_VERSION}"
    depends_on:
      - ziti-controller
    environment:
      - ZITI_CONTROLLER_RAWNAME="${ZITI_CONTROLLER_RAWNAME}"
      - ZITI_EDGE_CONTROLLER_RAWNAME="${ZITI_EDGE_CONTROLLER_RAWNAME}"
    env_file:
      - ./.env
    networks:
      ziti:
        aliases:
          - ziti-edge-controller-init-container
    volumes:
      - ziti-fs:/persistent
    entrypoint:
      - "/var/openziti/scripts/run-with-ziti-cli.sh"
    command:
      - "/var/openziti/scripts/access-control.sh"

  ziti-edge-router:
    image: "${ZITI_IMAGE}:${ZITI_VERSION}"
    depends_on:
      - ziti-controller
    environment:
      - ZITI_CONTROLLER_RAWNAME="${ZITI_CONTROLLER_RAWNAME}"
      - ZITI_EDGE_CONTROLLER_RAWNAME="${ZITI_EDGE_CONTROLLER_RAWNAME}"
      - ZITI_EDGE_ROUTER_RAWNAME=${ZITI_EDGE_ROUTER_RAWNAME:-ziti-edge-router}
      - ZITI_EDGE_ROUTER_ROLES=public
    ports:
      - ${ZITI_EDGE_ROUTER_PORT:-3022}:${ZITI_EDGE_ROUTER_PORT:-3022}
    networks:
      - ziti
    volumes:
      - ziti-fs:/persistent
    entrypoint: /bin/bash
    command: "/var/openziti/scripts/run-router.sh edge"

  ziti-console:
    image: openziti/zac
    depends_on:
      - ziti-controller
    working_dir: /usr/src/app
    environment:
      - ZAC_SERVER_CERT_CHAIN=/persistent/pki/${ZITI_EDGE_CONTROLLER_HOSTNAME:-ziti-controller}-intermediate/certs/${ZITI_EDGE_CONTROLLER_HOSTNAME:-ziti-controller}-server.cert
      - ZAC_SERVER_KEY=/persistent/pki/${ZITI_EDGE_CONTROLLER_HOSTNAME:-ziti-controller}-intermediate/keys/${ZITI_EDGE_CONTROLLER_HOSTNAME:-ziti-controller}-server.key
      - PORTTLS=8443
    ports:
      - 1408:1408
      - 8443:8443
    networks:
      - ziti
    volumes:
      - ziti-fs:/persistent

networks:
  ziti:

volumes:
  ziti-fs:

I’m using the following .env file, which is partly modified from this example. Some of the variables are overriden with my Oracle Cloud Instance information, for demonstration purposes let’s say that the public ip is 11.22.33.44 and the address I bought that’s pointing to that IP is ziti.jruiz.com.

# OpenZiti Variables
ZITI_IMAGE=openziti/quickstart
ZITI_VERSION=latest

# The duration of the enrollment period (in minutes), default if not set
# shown - 7days
ZITI_EDGE_IDENTITY_ENROLLMENT_DURATION=10080
ZITI_EDGE_ROUTER_ENROLLMENT_DURATION=10080

# controller address/port information
ZITI_CONTROLLER_RAWNAME=ziti-controller
ZITI_CONTROLLER_HOSTNAME=ziti.jruiz.com
#ZITI_CTRL_PORT=8440

ZITI_EDGE_CONTROLLER_RAWNAME=ziti-edge-controller
ZITI_EDGE_CONTROLLER_HOSTNAME=ziti.jruiz.com
#ZITI_EDGE_CONTROLLER_PORT=8441
ZITI_EDGE_CONTROLLER_IP_OVERRIDE=11.22.33.44

# router address/port information
ZITI_EDGE_ROUTER_RAWNAME=ziti.jruiz.com
#ZITI_EDGE_ROUTER_PORT=8442
ZITI_EDGE_ROUTER_IP_OVERRIDE=11.22.33.44

I first tried using Ziti’s Administration Console, but since it didn’t work, I decided to enter the Ziti Controller container (using the command docker exec -it <containerID> bash) and run the commands from the Minecraft tutorial manually.

For my tests I’m using my desktop which is acting as the host, running a Minecraft Bedrock Edition Dedicated Server on UDP port 57775 (Bedrock edition uses UDP instead of TCP just fyi)

Following the tutorial’s steps, these are the commands I’m running inside the Controller Container:

export DEVICE_NAME="jruiz.server"
export MY_NAME="jruiz.player"
export PORT=57775

ziti edge create identity device ${DEVICE_NAME} -o ${DEVICE_NAME}.jwt -a "${DEVICE_NAME}.hosts"
ziti edge create identity user ${MY_NAME} -o ${MY_NAME}.jwt -a "${DEVICE_NAME}.clients"

ziti edge create config ${DEVICE_NAME}.hostv1 host.v1 '{"protocol":"udp", "address":"localhost","port":'${PORT}'}'

ziti edge create config ${DEVICE_NAME}.interceptv1 intercept.v1 '{"protocols":["udp"],"addresses":["'${DEVICE_NAME}'.ziti"], "portRanges":[{"low":'${PORT}', "high":'${PORT}'}]}'

ziti edge create service ${DEVICE_NAME} --configs "${DEVICE_NAME}.hostv1,${DEVICE_NAME}.interceptv1"

ziti edge create service-policy "${DEVICE_NAME}.bind" Bind --service-roles "@${DEVICE_NAME}" --identity-roles "#${DEVICE_NAME}.hosts"

ziti edge create service-policy "${DEVICE_NAME}.dial" Dial --service-roles "@${DEVICE_NAME}" --identity-roles "#${DEVICE_NAME}.clients"

After this is done, I log into Ziti’s Administration Console and download the JWT to enroll it on my desktop and scan the QR code to enroll it on my phone (I have Minecraft on my phone to test)

Both edge apps, in desktop and phone, show the service that I created on UDP port 57775. However, I’m not able to connect to the Minecraft server on my desktop from my phone using address jruiz.server.ziti. (Just for the record, I can perfectly connect using regular LAN IPs)

Apart from the Minecraft Server, I’ve also tried testing with simple http python servers (of course creating their corresponding services/identities/policies, etc) but I’ve also had no luck. Any ideas? I can force delete and re-create all the containers/volumes if we need to test things to debug.

Thanks for all those details.

My guess is that the compose environment is not setting up the edge router advertised port quite right, leading to the clients not being able to connect. The quickstarts were more meant for a learning mechanism and not originally intended to be used in a long-term/production way, but that decision has been creating challenges for many people lately and we are now fixing that. We’re actively working on addressing this particular issue right now. If you can wait, maybe a week, we will hopefully have a better story to tell you on docker.

I’m happy to try to get this working for you sooner than that, but I think if you just wait a bit, we’ll have a much better docker experience very soon.

In the meantime, if you want to continue troubleshooting this, can you look at the logs from the phone that can’t connect for hints as to what it thinks “the problem” is? Same on the router. I would think that one or the other will have a very clear indicator as to what is wrong. I suspect either the client can’t connect to the edge router (as mentioned) or the router can’t offload from the overlay back to the underlay (to the minecraft server). You could probe/prove that by exec’ing to the router container and trying to ‘nc’ (netcat). For example, you should be able to run this and see “connection succeeded”:

netcat -vu your.minecraft.server.here 57775

You can try that with cloudflare DNS to see what it looks like:

$ netcat -vu 1.1.1.1 53
Connection to 1.1.1.1 53 port [udp/domain] succeeded!

I think it’ll be easier if we just publish instructions on how to use the containers in a ‘non-local’ way and update them for better/easier use.

Oh okay, it's nice to know that's already being addressed.

It's ok, I can wait :slight_smile: I'd really like to have everything set up using Docker and I'm not in a big hurry right now.

I'll try this when I have some time, perhaps the results can help you in some way :+1:

1 Like

I don’t know if this helps but I did what you mentioned using netcat like this (I changed the port to the default for Minecraft just in case because I’ve tried it multiple times deleting and recreating the docker compose containers)

nc -vu jruiz.server.ziti 19132

inside the ziti-edge-router container, and the output was

ziti@c620dae77fd8:/persistent$ nc -vu jruiz.server.ziti 19132
nc: getaddrinfo for host "jruiz.server.ziti" port 19132: Name or service not known

If I run the same command on localhost where I have the minecraft server, the output is as you described

➜  ~ nc -vu localhost 19132
Connection to localhost (127.0.0.1) 19132 port [udp/*] succeeded!

As I mentioned before, I’m in no hurry so I can wait for the improvements you mentioned. Btw, I don’t know if I can be of assistance but if so, please let me know!

I’m not quite sure I fully understand the topology that you have. “Usually” the docker container ends up figuring out the DNS server to upstream to. For the container to work, it would need to send a request to the DNS server that runs when the tunneler starts. That’s usually 100.64.0.2 (the default). I expect that when docker starts, ziti-edge-tunnel is not running, so docker doesn’t know about it, and thus doesn’t use it.

This is where a diagram from you would help me understand better how it all fits together, what you’re doing, where etc.

My guess is that the container is just not using the DNS provided by the tunneler when it starts but I’m not 100% sure.

Sure! This is my current topology:

Phone and desktop are not on the same network (i put my phone on mobile data to test it). I’ve also tested connecting the phone

As I explained on the first post, I opened the ports in the Oracle cloud instance, both in the ubuntu firewall from the server and in the Oracle Cloud Security Firewall (idk if that’s the correct name)

Let me know if you need to know something else, perhaps I’m missing out something.

Thanks for the diagram. You’re running the command nc -vu jruiz.server.ziti 19132 from the containers, that’s running in the Oracle VPS inside docker, and that’s when it does NOT work…

And running nc -vu localhost 19132 from the minecraft server works, which is sounds like is the minecraft server’s port…

That all makes PERFECT sense to me fwiw. That’s because you’re not running (well it’s not on the diagram) a ziti-edge-tunnel out on your VPS and there’s no “tunneler” telling the operating system on the Oracle VPS to “intercept” jruiz.server.ziti

The easiest way to verify/test this imo, would be to do the following:

  • ssh to the oracle vps
  • download the ziti-edge-tunnel or install it using a package manager. Whatever you find easier. see Linux | OpenZiti
  • once you have ziti-edge-tunnel command on the host OS (don’t run it in docker for this, just use the base OS), provision a new “test” identity like you did for the phone. i’ll call this vps-test-id.
  • grant the vps-test-id access to the minecraft server, service the same way you did for the phone
  • run the ziti-edge-tunnel on the VPS: ziti-edge-tunnel run -i /path/to/identity.json
  • at that point - your VPS should be able to netcat to the minecraft server from the Oracle VPS! :slight_smile:

That all make sense? I can mock up your diagram if that would help, but something tells me that probably makes sense to ya… If not though, lemme know.

THEN, i expect your Minecraft server netcat test to work… And if you want, you can provision me an identity and I’ll start minecraft and test it out for you… HEHEHEHEHE

Just a quick question or two
a) Are the identities showing as online in the console (one for the phone and one for the minecraft server) (double dots)
b) When you go into the identity on the phone, and you click the Minecraft service, does it say “Dial (Everything configured Correctly)”?

You shouldn’t have to jump onto mobile data to test either. You should be able to test on the same wifi/LAN network, and then move external when you get it working.

Also, looking at your config etc, it looks like the Edge router is listening on the default of 3022 (since ZITI_EDGE_ROUTER_PORT is not defined in the Env file. I cannot see that 3022 is open on the Ingress rules. (hence question around if you see the double dots in the console)

1 Like

Okay so I checked this first since it was just a matter of opening ports, and you were right, on the Server identity it didn't show the double dots when I didn't have 3022 port open. Now that's open, and it shows 2 dots for the server but not for the client

Interestingly, I added another client identity (same attributes as jruiz.player) and enrolled it on another Windows machine and it showed the double dots, but on Android still no double dots.

However it's still not working, the Minecraft client still doesn't resolve the jruiz.server.ziti address.

I'm unsure about where to check this, does this answer your question? (Bottom toast appears upon clicking on the text below "services")

(BTW sorry in advance about swapping between the ports 57775 and 19132, I'm doing a lot of testing and sometimes I mix up the ports but I take extreme care of not mixing them up while testing)

Aw shoot that makes total sense, since it doesn't have a tunneler it doesn't intercept anything, now i feel a lil dumb ahaha.

Is there any particular reason for which I can't test this using the Docker container for the tunneler? I'd prefer to keep this machine as clean as possible installing the lesser stuff the better, although if it's required for debugging, i'll do it.

Soory - slight typo in my quesion here:

Do this in the console instead. Edit the identity, and it will list the services that are available. Click on the service. On the "client" identity it should say "Dial is configured correctly". On the Server identity it should say "Bind, everything is configured correctly". If it does not, then check the policies or whatever.

Now that you have the double dots, it seems like the Ziti network is now working, just need to get the config right.

Not really, it's just not going to be 'isolated' in the way you would think/expect it to be. To run a tunneler in docker you need to grant the container extra privs, which docker then uses on the 'base' OS to "do things" (docker is "doing things to your network too fwiw)... It just complicates things to run it in the container and it's just so much easier to not do it that way imo. But you have another windows machine -- that's "just as good" anyway. All I really was recommending is that you test it "on some other machine" to make sure the overlay is configured properly.

So let's revise your diagram. This is what I want to test (I've omitted the controller for brevity.):

What we need to do now is a bit of troubleshooting. Here's what we need to do:

  • run policy advisor: ziti edge policy-advisor identities -q Here we'll be looking for output indicating that the identity jruiz.server has BIND capability for the minecraft service, and jruiz.client has DIAL capability for the minecraft service. You should NOT see something like:

    # you want to see this:
    OKAY : minecraftServer (1) -> minecraft (1) Common Routers: (1/1) Dial: N Bind: Y
     
    # not this
    ERROR: minecraftServer 
      - Identity does not have access to any services. Adjust service policies.
    
  • do the same thing for the `jruiz.client' but make sure you see Dial: Y like this:

    OKAY : minecraftClient (1) -> minecraft (1) Common Routers: (1/1) Dial: Y Bind: N
    
  • Assuming you have both of those, now you need to look at the logs on both the client side, and the server side. You're looking for ERRORs in those logs. You want to do the same thing for the edge-router logs too. If you want to email those to me to clint at openziti.org, I'll look at them.

Usually there's some kind of error that is quite straightforward for someone more familiar with ziti to understand (someone like me).

Using the ziti cli will take the ZAC out of the equation, which is probably a good idea at this time. I'm more familiar with looking at that output to be honest.

FYI: I have created an issue: Incorrect default ports on docker .env file · Issue #986 · openziti/ziti (github.com) to resolve the non-default ports defined in the default .env file.

Looking at the commands that you have written, I think this could be an issue as well.

ziti edge create service-policy "${DEVICE_NAME}.bind" Bind --service-roles "@${DEVICE_NAME}" --identity-roles "#${DEVICE_NAME}.hosts"

The bind identity should be the client identity, ie @${DEVICE_NAME}.

Here is an example of one I have:

@fp.csat.svc is the name of the service (${DEVICE_NAME}) by the looks
@cf.csat.identity is the identity of the device that I want the traffic to exit out of
#fp.csat.tag is what you add onto the identity that wants to access the service.

1 Like

Running that command inside the docker container for the edge router returns:

ERROR: Default Admin
  - Identity does not have access to any services. Adjust service policies.

ERROR: my.domain.jruiz.com
  - Identity does not have access to any services. Adjust service policies.

OKAY : jruiz.player (1) -> jruiz.server (1) Common Routers: (1/1) Dial: Y Bind: N

OKAY : jruiz.server (1) -> jruiz.server (1) Common Routers: (1/1) Dial: N Bind: Y

Seems okay to me? At least the server/client for the Minecraft endpoints, i don't know about the others

I've sent the logs for client and server applications, where can I find the logs for the edge router inside the container? I've sent you the logs from the docker container but I'm not so sure they are helpful. Also I think the problem might be at the server side? I see some weird errors with the controller.

I'm not so sure about that, because in your example you're using an identity but I'm using an attribute assigned to the identity.

This is how it looks in my ZAC

Btw I forgot to say this before but thank you so much for the support :heart: I'm learning a lot while debugging this.

Yes. All that looks perfect. In fact, thanks for the logs! I am pretty sure I see the problem. I’m transcribing my response via email here for everyone else to see too…

In the logs I could see this:

[2023-02-02T18:25:39.736Z] INFO tunnel-cbs:ziti_hosting.c:610 on_hosted_client_connect() hosted_service[jruiz.server], client[caca] dst_addr[udp:jruiz.server.ziti:57775]: incoming connection

So from that ONE line… you can see:

  • the service is named “jruiz.server” from this bit:

    hosted_service[jruiz.server]
    
  • the client connecting was named “caca” from this bit:

    client[caca]
    
  • the “destination” address from this bit:

    dst_addr[udp:jruiz.server.ziti:57775]
    

The destination appears to be wrong. When you filled out the “host.v1” configuration, did you use “localhost” or did you use jruiz.server.ziti? I am 99% sure you used jruiz.server.ziti or there’s a bug somewhere. Instead, you want to use “localhost”. The host.v1 config is telling the tunneller running on the server to offload traffic ‘somewhere’. Since it’s the ziti desktop edge for windows, and that’s where Minecraft is running, you want that to be “localhost”…

Can you show us what the config looks like in ZAC? Does it use localhost like this?

image

Okay so first of all, sorry for not answering sooner. I had to deal with some personal/work stuff.

Second, about this:

Im sorry, this might have been misleading to you... but this client you mention is a dummy client (with a silly spanish name... facepalm) i made to do some tests on another machine...

I've been testing with so many tokens i've lost count and I think the logs are contaminated with unrelated stuff (for example, before posting the question here, I've deleted and recreated the docker compose stack a couple times, and the Ziti edge apps tried to connect with an old enrollment token and there is some noise in the logs regarding that)

I think the best way to go here is to do a fresh start. Tear down every docker container and volume and start from scratch. Also, I'm going to use the default Minecraft Bedrock UDP port 19132 instead of a custom one just for the sake of simplicity.

I've uninstalled completely the Ziti Edge Desktop and mobile apps. Also, and again, for the sake of simplicity, I'm going to use a Windows laptop as the client instead of the Android one. The reason for this is that it's more comfortable to extract logs from there.

So, I know im going to repeat myself but better be 100% clear, starting from the oracle cloud instance, the firewall has the following open ports

And the firewalld configuration is as follows:

ubuntu@jruizmachine:~$ sudo firewall-cmd --list-all
You're performing an operation over default zone ('public'),
but your connections/interfaces are in zone 'docker' (see --get-active-zones)
You most likely need to use --zone=docker option.

public
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: dhcpv6-client ssh
  ports: 8441/tcp 8442/tcp 6262/tcp 10080/tcp 8443/tcp 1280/tcp 3022/tcp
  protocols:
  forward: yes
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

NOTE: I just noticed the message saying that my connections interfaces are in zone 'docker'... I'm unsure if that's related to my issue...

I've done the following to delete and recreate the docker compose stack

docker compose down
docker system prune -a && docker volume rm $(docker volume ls -q)

This should clear everything from containers/images to volumes (if not, let me know)

Then goes docker compose up

Then I've entered the ziti-edge-router container to run some commands.

The commands I posted before were copied and pasted from the Minecraft tutorial, and some variable names were a little bit confusing, so I've made some changes.

These are the commands I've run inside the container

zitiLogin

export SERVER_DEVICE_NAME="jruiz.server"
export CLIENT_DEVICE_NAME="jruiz.client"
export PORT=19132

ziti edge create identity device ${SERVER_DEVICE_NAME} -o ${SERVER_DEVICE_NAME}.jwt -a "${SERVER_DEVICE_NAME}.hosts"
ziti edge create identity user ${CLIENT_DEVICE_NAME} -o ${CLIENT_DEVICE_NAME}.jwt -a "${SERVER_DEVICE_NAME}.clients"

ziti edge create config ${SERVER_DEVICE_NAME}.hostv1 host.v1 '{"protocol":"udp", "address":"localhost","port":'${PORT}'}'

ziti edge create config ${SERVER_DEVICE_NAME}.interceptv1 intercept.v1 '{"protocols":["udp"],"addresses":["'${SERVER_DEVICE_NAME}'.ziti"], "portRanges":[{"low":'${PORT}', "high":'${PORT}'}]}'

ziti edge create service ${SERVER_DEVICE_NAME} --configs "${SERVER_DEVICE_NAME}.hostv1,${SERVER_DEVICE_NAME}.interceptv1"

ziti edge create service-policy "${SERVER_DEVICE_NAME}.bind" Bind --service-roles "@${SERVER_DEVICE_NAME}" --identity-roles "#${SERVER_DEVICE_NAME}.hosts"

ziti edge create service-policy "${SERVER_DEVICE_NAME}.dial" Dial --service-roles "@${SERVER_DEVICE_NAME}" --identity-roles "#${SERVER_DEVICE_NAME}.clients"

Then I've installed Ziti Desktop Edge on the Server machine, and enrolled the JWT token. Done the same on the client machine.

This is how everything looks in the ZAC

In the image below, the port says 19132 but it doesn't show the last digit (i've checked)

I've started the Minecraft Bedrock Server on port 19132 on the server machine

Tried to reach that using the client machine, no success. Just to double check, trying to access localhost:19132 on the Windows desktop works (i tested just in case...)

@TheLumberjack I'm sending you the logs again via email because it doesn't let me attach them to the forum post

Hopefully I don't forget to censor my custom domain and name (and no silly spanish names...)

I know i repeat myself a lot, but thanks a ton for the patience and the support :heart:

Hi @jruiz94. I would expect you’re running the java version of minecraft right? I had to go through the whole process myself… Java Minecraft server runs on tcp not udp. I think that’ll fix your problem up. I ran all the same commands you supplied and it worked fine once i checked udp vs tcp

I gather you have tried the following command and it is returning as per previous posts?

On the windows client, if you ping jruiz.server.ziti I gather it is resolving to a 100.x.x.x address - this confirms that the intercept in pushing traffic over the overlay.

Hi again. No, I was using Bedrock edition. Bedrock edition uses UDP AFAIK.

However, I should've tried with Minecraft Java because... you're absolutely right. It works. I mean, I have created another service to leave the UDP one as it was just in case, so I added an intercept for jruiz.server.tcp.ziti with a TCP port and the policy dial/bind and BOOM it worked instantly and flawlessly.

Soooo I don't know, seems like everything was good all along (except perhaps the closed port 3022 I had that @gooseleggs mentioned) and I got hard trolled by Microsoft and its Bedrock Minecraft thing or something... I don't know.

I'm still kinda puzzled on what might be wrong about the UDP Minecraft Bedrock setup. Like I want to know if it's a firewall thing or something? I don't know. But anyway, that's a non-OpenZiti related issue and I'm super happy to have this fixed and working on Docker!

Thanks a lot again to both of you :heart: