**type or paste code here**import requests
import os
import json
import time
import subprocess
# Environment variables
FLY_API_TOKEN = os.getenv('FLY_API_TOKEN')
FLY_API_HOSTNAME = 'https://api.machines.dev'
APP_NAME = 'streamlit-hello-world'
headers = {
'Authorization': f'Bearer {FLY_API_TOKEN}',
'Content-Type': 'application/json'
}
def run_fly_command(command):
"""Execute a fly CLI command and return the output"""
try:
result = subprocess.run(
command,
check=True,
text=True,
capture_output=True
)
return result.stdout
except subprocess.CalledProcessError as e:
print(f"Command failed with exit code {e.returncode}")
print(f"Error output: {e.stderr}")
return None
def create_app():
"""Create the application"""
url = f"{FLY_API_HOSTNAME}/v1/apps"
app_payload = {
"app_name": APP_NAME,
"org_slug": "personal"
}
try:
response = requests.post(url, headers=headers, json=app_payload)
response.raise_for_status()
print("App created successfully!")
return response.json()
except requests.exceptions.RequestException as e:
if hasattr(e, 'response') and e.response.status_code == 409:
print("App already exists, continuing...")
else:
print(f"Error creating app: {e}")
raise
def allocate_ips_with_cli():
"""Allocate IPs using fly CLI"""
print("Allocating IPv4...")
run_fly_command(['fly', 'ips', 'allocate-v4', '--shared', '-a', APP_NAME])
print("Allocating IPv6...")
run_fly_command(['fly', 'ips', 'allocate-v6', '-a', APP_NAME])
# Show allocated IPs
print("\nAllocated IPs:")
run_fly_command(['fly', 'ips', 'list', '-a', APP_NAME])
def deploy_machine():
"""Deploy the machine with Streamlit"""
url = f"{FLY_API_HOSTNAME}/v1/apps/{APP_NAME}/machines"
machine_config = {
"name": APP_NAME,
"config": {
"image": "python:3.9-slim",
"env": {
"PORT": "8501"
},
"services": [
{
"ports": [
{
"port": 443,
"handlers": ["tls", "http"]
},
{
"port": 80,
"handlers": ["http"]
}
],
"protocol": "tcp",
"internal_port": 8501
}
],
"guest": {
"cpu_kind": "shared",
"cpus": 2,
"memory_mb": 1024
},
"init": {
"exec": [
"/bin/sh",
"-c",
"""
apt-get update && apt-get install -y git &&
pip install streamlit &&
echo 'import streamlit as st\n\nst.title("Hello World!")\nst.write("Welcome to Streamlit!")' > app.py &&
streamlit run app.py --server.address 0.0.0.0 --server.port 8501
"""
]
}
}
}
try:
response = requests.post(url, headers=headers, json=machine_config)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error deploying machine: {e}")
if hasattr(e, 'response'):
print(f"Response Status: {e.response.status_code}")
print(f"Response Body: {e.response.text}")
raise
def check_machine_status(machine_id):
"""Check the status of a machine"""
url = f"{FLY_API_HOSTNAME}/v1/apps/{APP_NAME}/machines/{machine_id}"
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error checking machine status: {e}")
return None
def main():
try:
# Create app
create_app()
# Allocate IPs using CLI
print("Allocating IPs using CLI...")
allocate_ips_with_cli()
# Deploy machine
print("Deploying machine...")
machine_response = deploy_machine()
machine_id = machine_response['id']
print(f"Machine deployed with ID: {machine_id}")
# Monitor deployment
print("Monitoring deployment...")
max_attempts = 10
attempt = 0
while attempt < max_attempts:
status = check_machine_status(machine_id)
if status:
state = status.get('state', '')
print(f"Current state: {state}")
if state == 'started':
print("\nDeployment successful!")
print(f"Your app should be available at: https://{APP_NAME}.fly.dev")
# Show final IP allocation using CLI
print("\nFinal IP allocation:")
run_fly_command(['fly', 'ips', 'list', '-a', APP_NAME])
break
time.sleep(5)
attempt += 1
if attempt >= max_attempts:
print("Deployment monitoring timed out")
except Exception as e:
print(f"An error occurred: {str(e)}")
if __name__ == "__main__":
main()
Hi… I don’t see any IP addresses assigned to streamlit-hello-world.fly.dev
, and it looks your Python code is trapping exceptions from the flyctl
subprocess during their allocation. (And then just continuing…)
What do fly ips list -a streamlit-hello-world
and fly m list -a streamlit-hello-world
show, at present?
hey i have deleted the apps thats why its not showing
finally figure out the issue is when running the script for the first time even after all the ssh logs and instance is active but the website is saying not reachable but creating the new app its working here is the app name 1. streamlit-hello3 which is not working but with the same script streamlit-hello4 its working I dont know some strange bug or issue
also if i want to add this
auto_start_machines = true
auto_stop_machines = true
where can i add instead of toml
Now all the apps are working even streamlit-hello3 but it took almost 20-30 mins i think this would be the dns issue
Your machine_config
plays the role of fly.toml
when using the Machines API.
(Or rather, the TOML file is a convenient serialization of that eventual JSON payload, for the most part.)
There are tons of possible knobs there, but it looks like the auto-start ones go in the service block, at the same level as internal_port
.
In general, though, your current approach of running apt-get install
in the exec
is going to cause you major grief. All of that will be repeated every time your Machine is woken up to service a new request, .
You really want to create a Dockerfile and make a new image instead…
Hey thanks for the guide It was just a sample code to test the workflow here is the template image.
also if you have could help in telling the optimise way to update the file in the deployment what i mean is
i have app.py which is running default in the docker container in flyio CMD ["streamlit", "run", "app.py", "--server.port=8505", "--server.address=0.0.0.0"]
i want to update the content in app.py right now i have written ssh logic to do ssh and delete the current file and copy the new app.py because when using copy or move command its saying file alredy exist but i know if the machine sleeps and wake up the machine is bringing the old app.py
import requests
import os
import json
import time
import subprocess
# Environment variables
FLY_API_TOKEN = os.getenv('FLY_API_TOKEN')
FLY_API_HOSTNAME = 'https://api.machines.dev'
APP_NAME = 'streamlit-hello70'
headers = {
'Authorization': f'Bearer {FLY_API_TOKEN}',
'Content-Type': 'application/json'
}
def run_fly_command(command):
"""Execute a fly CLI command and return the output"""
try:
result = subprocess.run(
command,
check=True,
text=True,
capture_output=True
)
return result.stdout
except subprocess.CalledProcessError as e:
print(f"Command failed with exit code {e.returncode}")
print(f"Error output: {e.stderr}")
return None
def create_app():
"""Create the application"""
url = f"{FLY_API_HOSTNAME}/v1/apps"
app_payload = {
"app_name": APP_NAME,
"org_slug": "personal"
}
try:
response = requests.post(url, headers=headers, json=app_payload)
response.raise_for_status()
print("App created successfully!")
return response.json()
except requests.exceptions.RequestException as e:
if hasattr(e, 'response') and e.response.status_code == 409:
print("App already exists, continuing...")
else:
print(f"Error creating app: {e}")
raise
def allocate_ips_with_cli():
"""Allocate IPs using fly CLI"""
print("Allocating IPv4...")
run_fly_command(['fly', 'ips', 'allocate-v4', '--shared', '-a', APP_NAME])
print("Allocating IPv6...")
run_fly_command(['fly', 'ips', 'allocate-v6', '-a', APP_NAME])
# Show allocated IPs
print("\nAllocated IPs:")
run_fly_command(['fly', 'ips', 'list', '-a', APP_NAME])
def deploy_machine():
"""Deploy the machine with Streamlit"""
url = f"{FLY_API_HOSTNAME}/v1/apps/{APP_NAME}/machines"
machine_config = {
"name": APP_NAME,
"config": {
"image": "registry.fly.io/muatafastreamlit-26:deployment-01JD0WHTRR6B7XZDTTABN6DDN3",
"env": {
"PORT": "8505"
},
"services": [
{
"ports": [
{
"port": 443,
"handlers": ["tls", "http"]
},
{
"port": 80,
"handlers": ["http"]
}
],
"protocol": "tcp",
"internal_port": 8505
}
],
"guest": {
"cpu_kind": "shared",
"cpus": 2,
"memory_mb": 512
}
}
}
try:
response = requests.post(url, headers=headers, json=machine_config)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error deploying machine: {e}")
if hasattr(e, 'response'):
print(f"Response Status: {e.response.status_code}")
print(f"Response Body: {e.response.text}")
raise
def check_machine_status(machine_id):
"""Check the status of a machine"""
url = f"{FLY_API_HOSTNAME}/v1/apps/{APP_NAME}/machines/{machine_id}"
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error checking machine status: {e}")
return None
def main():
try:
# Create app
create_app()
# Allocate IPs using CLI
print("Allocating IPs using CLI...")
allocate_ips_with_cli()
# Deploy machine
print("Deploying machine...")
machine_response = deploy_machine()
machine_id = machine_response['id']
print(f"Machine deployed with ID: {machine_id}")
# Monitor deployment
print("Monitoring deployment...")
max_attempts = 10
attempt = 0
while attempt < max_attempts:
status = check_machine_status(machine_id)
if status:
state = status.get('state', '')
print(f"Current state: {state}")
if state == 'started':
print("\nDeployment successful!")
print(f"Your app should be available at: https://{APP_NAME}.fly.dev")
# Show final IP allocation using CLI
print("\nFinal IP allocation:")
run_fly_command(['fly', 'ips', 'list', '-a', APP_NAME])
break
time.sleep(2)
attempt += 1
if attempt >= max_attempts:
print("Deployment monitoring timed out")
except Exception as e:
print(f"An error occurred: {str(e)}")
if __name__ == "__main__":
main()
Right, for permanent changes you would generate a fresh image (with the new app.py
inside). Then, POST
a revised machine_config
to the Machine update endpoint instead of the Machine create one:
/v1/apps/{APP_NAME}/machines/{machine_id}
^^^^^^^^^^
already existing
You can get these IDs from the handy list URL or just by remembering them from earlier.
I often do make (temporary) changes within a live machine over SSH and then fold those back into the repeatable image definition significantly afterward—but most people tend to develop almost exclusively locally.
This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.