That totally makes sense. Here’s roughly the queries and mutations you’ll need to get the job done along with a link to the flyctl source as a reference. This is certainly a lot of steps, but your use case is neat and we’d like to make it easier someday.
1. Get your organization ID (flyctl)
You’ll need this node id when creating the app
query {
organization(slug: "your-org") {
id
}
}
2. Create App (flyctl)
This creates a pending app. Note the app id and name are the same right now, but it’s best to pass the value from the ID field when calling mutations.
Variables:
{
"organizationId": "your-org-id",
"name": "app-name"
}
Mutation:
mutation($input: CreateAppInput!) {
createApp(input: $input) {
app {
id
name
}
}
}
3. Prepare Image (flyctl)
Before deploying a docker image you’ll need to prep it with the optimizeImage
mutation. This generates a flattened rootfs file from the image in the background. Since it’s async you’ll need to poll until you get the READY
status. These rootfs files are reused for identical images, so you typically only see a delay when the image changes.
Variables:
{
"appId": "your-app",
"image": "your/image:latest"
}
Mutation:
mutation($input: OptimizeImageInput!) {
optimizeImage(input: $input) {
status
}
}
All you need to deploy is the app id, image reference, and definition. The definition is the JSON representation of the fly.toml file.
This mutation returns immediately while the app deploys in the background.
Variables:
{
"appId": "your-app",
"image": "your/image:latest",
"definition": {
"env": {
"LOG_LEVEL": "info",
"DATABASE_URL": "postgres://...",
},
"services": [
{
"protocol": "tcp",
"internal_port": 8080,
"concurrency": {
"soft_limit": 20,
"hard_limit": 25
},
"ports": [
{
"port": "80",
"handlers": ["http"]
},
{
"port": "443",
"handlers": ["http", "tls"]
}
],
"http_checks": [
{
"interval": 10000,
"timeout": 2000,
"method": "get",
"protocol": "http",
"path": "/status",
"tls_skip_verify": false,
"headers": {}
}
],
}
]
}
}
Mutation
mutation($input: DeployImageInput!) {
deployImage(input: $input) {
release {
id
}
}
}
5. Check Deployment Status (flyctl)
You’ll need to poll to monitor the deployment. You can use an empty string as the deployment id to query the most recent deployment. Look at inProgress
and successful
to determine if the deployment is complete. Note that sometimes it takes a few seconds for the deployment to be created after calling the deployImage
mutation.
Variables:
{
"appName": "your-app",
"deploymentId": ""
}
Query:
query ($appName: String!, $deploymentId: ID!) {
app(name: $appName) {
deploymentStatus(id: $deploymentId) {
id
inProgress
status
successful
description
version
desiredCount
placedCount
healthyCount
unhealthyCount
}
}
}