The Simplest Python UDP app (Help!)

I’m trying to deploy the simplest python app ever to receive UDP messages. simply.py looks like this:

import socket

print("Hello Fly.io!")

UDP_IP = "fly-global-services"
UDP_PORT = 5000

sock = socket.socket(socket.AF_INET, 
                     socket.SOCK_DGRAM) 
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
    print("received message: %s" % data)

the fly.toml looks like this

# fly.toml file generated for hellopython on 2022-04-15T04:05:30+01:00

app = "hellopython"

kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[env]
  PORT = "5000"

[experimental]
  allowed_public_ports = []
  auto_rollback = true

[[services]]
  internal_port = 5000
  processes = ["app"]
  protocol = "udp"

  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    port = "5000"

[[statics]]
  guest_path = "/app/public"
  url_prefix = "/static/"

the Dockerfile file:

ARG PYTHON_VERSION=3.7

FROM python:${PYTHON_VERSION}

RUN apt-get update && apt-get install -y \
    python3-pip \
    python3-venv \
    python3-dev \
    python3-setuptools \
    python3-wheel

RUN mkdir -p /app
WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .


EXPOSE 5000

# replace APP_NAME with module name
CMD ["python", "simply.py"]

and the Procfile:

web: python simply.py

No matter what I do, I always get an error (on the logs) like this:

2022-04-15T03:16:30.769 runner[ab129be9] lhr [info] Starting virtual machine
2022-04-15T03:16:31.189 app[ab129be9] lhr [info] Starting init (commit: 252b7bd)...
2022-04-15T03:16:31.189 app[ab129be9] lhr [info] Preparing to run: `python simply.py` as root
2022-04-15T03:16:31.190 app[ab129be9] lhr [info] 2022/04/15 03:16:31 listening on [fdaa:0:5a7f:a7b:276d:ab12:9be9:2]:22 (DNS: [fdaa::3]:53)
2022-04-15T03:16:56.515 runner[b2f6e65b] lhr [info] Shutting down virtual machine
2022-04-15T03:16:56.851 app[b2f6e65b] lhr [info] Sending signal SIGINT to main child process w/ PID 515
2022-04-15T03:16:56.854 app[b2f6e65b] lhr [info] Traceback (most recent call last):
2022-04-15T03:16:56.854 app[b2f6e65b] lhr [info]   File "simply2.py", line 14, in 
2022-04-15T03:16:56.854 app[b2f6e65b] lhr [info]     data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
2022-04-15T03:16:56.854 app[b2f6e65b] lhr [info] KeyboardInterrupt
2022-04-15T03:16:56.854 app[b2f6e65b] lhr [info] Hello Fly.io!
2022-04-15T03:16:57.856 app[b2f6e65b] lhr [info] Main child exited normally with code: 1
2022-04-15T03:16:57.857 app[b2f6e65b] lhr [info] Starting clean up.

Can someone please explain to me what I am doing wrong, and how can I make this work?
I’m pretty lost here. Any help will be greatly appreciated.

Thank you

I’m not sure! I took your code verbatim, made an empty requirements.txt, took your Dockerfile, did a flyctl launch, edited fly.toml and copied your service definition (which looks fine!) into it, then deployed; it’s running now. I can shell into it with flyctl ssh console, install tcpdump with apt-get install -y tcpdump, and see UDP packets arriving on its IP address.

Some quick notes:

  • Nothing in your Dockerfile uses a Procfile (you just exec the Python program, which seems fine)

  • The EXPOSE in your Dockerfile doesn’t do anything (we don’t honor EXPOSE, and what’s in your fly.toml pretty much controls).

1 Like

@thomas thank you so much for helping me with this! And for explaining that!

How do you do that? When I try that I see on my terminal

$  flyctl ssh console
Update available 0.0.320-pre-1 -> v0.0.320.
Run "flyctl version update" to upgrade.
Connecting to top1.nearest.of.firstfly.internal... complete
Error error connecting to SSH server: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain

and on the logs online

2022-04-15T11:42:44.509 app[88283b4f] lhr [info] 2022/04/15 11:42:44 unexpected error: transient SSH server error: can't resolve _orgcert.internal
2022-04-15T11:42:44.617 app[88283b4f] lhr [info] 2022/04/15 11:42:44 unexpected error: [ssh: no auth passed yet, transient SSH server error: can't resolve _orgcert.internal]

I also tried:

$  flyctl ssh establish
Update available 0.0.320-pre-1 -> v0.0.320.
Run "flyctl version update" to upgrade.
Automatically selected personal organization: #####
Establishing SSH CA cert for organization personal
Error establish key failed: key exists and override not set

///////////

So, I decided to do it from scratch again, following the steps you took. And now it doesn’t crash on the log online but it also doesn’t print the “Hello Fly.io!” message, nor receive my UDP messages. For reference:

again, this is the python script I am using
import socket

print("Hello Fly.io!")

UDP_IP = "fly-global-services"
UDP_PORT = 5000

sock = socket.socket(socket.AF_INET, 
                     socket.SOCK_DGRAM) 
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
    print("received message: %s" % data)
this is the Dockerfile I am using
ARG PYTHON_VERSION=3.7

FROM python:${PYTHON_VERSION}

RUN apt-get update && apt-get install -y \
    python3-pip \
    python3-venv \
    python3-dev \
    python3-setuptools \
    python3-wheel

RUN mkdir -p /app
WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .


# replace APP_NAME with module name
CMD ["python", "simply.py"]
this is what the modified fly.toml looks like
# fly.toml file generated for firstfly on 2022-04-15T12:39:30+01:00

app = "firstfly"

kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[env]
  PORT = "5000"

[experimental]
  allowed_public_ports = []
  auto_rollback = true

[[services]]
  internal_port = 5000
  processes = ["app"]
  protocol = "udp"

  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    port = "5000"

[[statics]]
  guest_path = "/app/public"
  url_prefix = "/static/"
and this is the python script I am using to send UDP messages
import socket

UDP_IP = "firstfly.fly.dev"
UDP_PORT = 5000
MESSAGE = b"Hello, World!"

print("UDP target IP: %s" % UDP_IP)
print("UDP target port: %s" % UDP_PORT)
print("message: %s" % MESSAGE)

sock = socket.socket(socket.AF_INET, 
                     socket.SOCK_DGRAM) 
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

here is the flyctl version:

flyctl v0.0.320-pre-1 darwin/amd64 Commit: 58aae1e BuildDate: 2022-04-13T12:19:08Z

Using fly wireguard websockets enable, following instructions received here.

And running on mac 10.15.7 Python 3.7.3.
Please let me know what else you think we can do next.
I appreciate your help trying to figure this out!

Hi again @thomas
Sorry for the double-post.

I just tried running flyctl deploy --no-cache for good measure, even though I just had built everything from scratch just like you did, on a new folder. and now I am back at getting the app to crash. the logs show:

2022-04-15T12:07:00.209 runner[ebda2dab] lhr [info] Configuring virtual machine
2022-04-15T12:07:08.477 runner[ebda2dab] lhr [info] Starting virtual machine
2022-04-15T12:07:34.220 runner[edfc2695] lhr [info] Shutting down virtual machine
2022-04-15T12:07:34.436 app[edfc2695] lhr [info] Sending signal SIGINT to main child process w/ PID 515
2022-04-15T12:07:34.438 app[edfc2695] lhr [info] Hello Fly.io!
2022-04-15T12:07:34.438 app[edfc2695] lhr [info] Traceback (most recent call last):
2022-04-15T12:07:34.438 app[edfc2695] lhr [info]   File "simply.py", line 13, in 
2022-04-15T12:07:34.438 app[edfc2695] lhr [info]     data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
2022-04-15T12:07:34.438 app[edfc2695] lhr [info] KeyboardInterrupt
2022-04-15T12:07:35.439 app[edfc2695] lhr [info] Main child exited normally with code: 1
2022-04-15T12:07:35.439 app[edfc2695] lhr [info] Starting clean up.

I feel so lost…

So, it seems that I’ve been able to interact with the app even though the logs say it is crashed.
I am realizing now that most of the time I have been fooled by fly.io logs. This really sucks that we can’t rely on it to give updated information about the app.
I’ve been seeing errors pop out from previous deploy iterations, I’ve seen messages getting stuck and then coming out all at the same time (in the timestamps too), I learned the restart command and seen it sometimes do absolutely nothing… this is really, truly unreliable. And just yet another thing to confuse the newcomer.
(I still can’t believe how many hours I’ve wasted because of this.)

1 Like