Creating apps (deployments? services?) with the CLI

Noob… apologies!

Koyeb is interesting.

I’ve a strong preference for CLI > UI.

I was able to deploy an app using the UI but would prefer to do this using the CLI.

It’s unclear to me:

  1. Whether it’s possible to use the CLI to deploy an app
  2. Deploy an application uses app init flags. Is the CLI fully-equivalent to the UI for app deployment?
  3. Is there an app spec (YAML?) that fully defines apps and can be used with the CLI?
  4. After deploying an app, I can app list, service list and deployment list; the difference between these resource types is unclear (documented?)

My primary cloud platform is Google but I deploy to Azure, Linode, Vultr and Fly also.

hey!

We are currently working on the CLI to improve it. Currently it’s working, but the experience using it is far from ideal.

At the moment, it is possible to deploy applications with koyeb app init or koyeb app create then koyeb service create.

For examples, you can run the help subcommand or checkout our custom github action which wraps the CLI.

It is not possible to have an app spec that defines the application but it’s a great idea!

Regarding the differences between the app, service and deployment:

  • services are inside applications, and can communicate between each other directly. For example, if the services api and worker are in the same application, they can use the private domains api or worker to reach each other.
  • the deployment defines how your application runs: if you update a service with a scale of 4, we will create a new deployment for your service, and 4 “regional deployments”: one per instance running your service. With koyeb deployment list , you can see a revision history of your service.
1 Like

This is very helpful, thank you!

I did not see this explanation in the service’s documentation and think, if it’s not currently explained there, that it would be helpful information to include.

1 Like

Hi Julien, any progress on this ?
Currently I am trying hard to use the CLI in my yml action file to deploy a Dockerized app (a duckdb/fastapi/prometheus combo).

I have a hard time :dizzy_face:

koyeb service deploy --config ./koyeb.yaml --app duckdb-spawn --token ${{ secrets.KOYEB_TOKEN }}

name: duckdb-spawn
services:
  - name: api
    type: docker
    docker:
      image: ${{ secrets.DOCKER_HUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
    ports:
      - name: http
        port: 8000
    env:
      - name: DATABASE_URL
        value: /data/duckdb_spawn.db
    resources:
      cpu: 500m
      memory: 512Mi
    regions:
      - fra

Can’t find a definitive guide or doc on setup of github actions to deploy on Koyeb.

Help or pointer appreciated.

regards

(post deleted by author)

1 Like

Pas si vite – I succeeded in creating an app, but not in spawning the service from my docker image.

Can you help me set the right Github action?

I have the image properly built in my docker hub (and it is accessed through my docker secrets) .

It seems that although I specify a type : docker in the koyeb.yaml file, the koyeb services create expects some github information.

I get the following errors in the Github action run

koyeb apps create duckdb-spawn --config ./koyeb.yaml --token *** --debug
  koyeb services create duckdb-spawn/api --config ./koyeb.yaml --token *** --debug
  shell: /usr/bin/bash -e {0}
  env:
    DOCKER_HUB_USERNAME: ***
    DOCKER_IMAGE_NAME: duckdb-spawn
    KOYEB_APP_NAME: duckdb-spawn
time="2024-11-21T17:22:41Z" level=debug msg="Using config file: ./koyeb.yaml"
time="2024-11-21T17:22:42Z" level=debug msg="Using host: app.koyeb.com using https"
time="2024-11-21T17:22:42Z" level=debug msg="Unable to find setter SetHelp on *koyeb.CreateApp\n"
time="2024-11-21T17:22:42Z" level=debug msg="========== HTTP request ==========\nPOST /v1/apps HTTP/1.1\r\nHost: app.koyeb.com\r\nUser-Agent: koyeb-cli/5.3.0\r\nContent-Length: 24\r\nAccept: */*\r\nAuthorization: <HIDDEN, add --debug-full to show the token>\nContent-Type: application/json; charset=utf-8\r\nAccept-Encoding: gzip\r\n\r\n{\"name\":\"duckdb-spawn\"}\n\n========== end of request ==========\n"
time="2024-11-21T17:22:42Z" level=debug msg="========== HTTP response ==========\nHTTP/2.0 200 OK\r\nCache-Control: no-cache, no-store\r\nContent-Type: application/json\r\nDate: Thu, 21 Nov 2024 17:22:42 GMT\r\nPragma: no-cache\r\nStrict-Transport-Security: max-age=15724800; includeSubDomains\r\nVary: Accept-Encoding\r\nX-Ratelimit-Limit: 30, 30;w=60\r\nX-Ratelimit-Remaining: 29\r\nX-Ratelimit-Reset: 18\r\n\r\n{\"app\":{\"id\":\"2635617b-9ed4-4491-a10e-3bcd18be5129\",\"name\":\"duckdb-spawn\",\"organization_id\":\"907de27c-acaa-4573-bf2a-3a7d34ce0baa\",\"created_at\":\"2024-11-21T17:22:42.595491Z\",\"updated_at\":\"2024-11-21T17:22:42.595491Z\",\"started_at\":null,\"succeeded_at\":null,\"paused_at\":null,\"resumed_at\":null,\"terminated_at\":null,\"status\":\"STARTING\",\"messages\":[\"App starting.\"],\"version\":\"0\",\"domains\":[{\"id\":\"6e23c8fb-9327-4e7e-ba6a-0b7524c0a58d\",\"organization_id\":\"907de27c-acaa-4573-bf2a-3a7d34ce0baa\",\"name\":\"duckdb-spawn-dealexmachina-b837970c.koyeb.app\",\"created_
ID      	NAME        	STATUS  	DOMAINS                                          	CREATED AT          
2635617b	duckdb-spawn	STARTING	["duckdb-spawn-dealexmachina-b837970c.koyeb.app"]	21 Nov 24 17:22 UTC	
time="2024-11-21T17:22:42Z" level=debug msg="Using config file: ./koyeb.yaml"
time="2024-11-21T17:22:42Z" level=debug msg="Using host: app.koyeb.com using https"
time="2024-11-21T17:22:42Z" level=debug msg="========== HTTP request ==========\nGET /v1/apps?limit=100&offset=0 HTTP/1.1\r\nHost: app.koyeb.com\r\nUser-Agent: koyeb-cli/5.3.0\r\nAccept: */*\r\nAuthorization: <HIDDEN, add --debug-full to show the token>\nAccept-Encoding: gzip\r\n\r\n\n========== end of request ==========\n"
time="2024-11-21T17:22:43Z" level=debug msg="========== HTTP response ==========\nHTTP/2.0 200 OK\r\nCache-Control: no-cache, no-store\r\nContent-Type: application/json\r\nDate: Thu, 21 Nov 2024 17:22:43 GMT\r\nPragma: no-cache\r\nStrict-Transport-Security: max-age=15724800; includeSubDomains\r\nVary: Accept-Encoding\r\nX-Ratelimit-Limit: 200, 200;w=60\r\nX-Ratelimit-Remaining: 199\r\nX-Ratelimit-Reset: 17\r\n\r\n{\"apps\":[{\"id\":\"bd805dc9-47f7-4e9e-acce-88d0ad6499c6\",\"name\":\"koyeb-db-preview-app\",\"organization_id\":\"907de27c-acaa-4573-bf2a-3a7d34ce0baa\",\"updated_at\":\"2024-05-07T07:00:59.767248Z\",\"created_at\":\"2024-05-07T07:00:30.667617Z\",\"domains\":[{\"id\":\"ae95a7e5-b488-4020-90dc-e695efb9f5c6\",\"organization_id\":\"907de27c-acaa-4573-bf2a-3a7d34ce0baa\",\"name\":\"koyeb-db-preview-app-dealexmachina-592b4f11.koyeb.app\",\"created_at\":\"2024-05-07T07:00:30.682003Z\",\"updated_at\":\"2024-05-07T07:00:30.682003Z\",\"status\":\"ACTIVE\",\"type\":\"AUTOASSIGNED\",\"app_id\":\"bd805dc9-47f7
time="2024-11-21T17:22:43Z" level=debug msg="========== HTTP request ==========\nGET /v1/apps/2635617b-9ed4-4491-a10e-3bcd18be5129 HTTP/1.1\r\nHost: app.koyeb.com\r\nUser-Agent: koyeb-cli/5.3.0\r\nAccept: */*\r\nAuthorization: <HIDDEN, add --debug-full to show the token>\nAccept-Encoding: gzip\r\n\r\n\n========== end of request ==========\n"
time="2024-11-21T17:22:43Z" level=debug msg="========== HTTP response ==========\nHTTP/2.0 200 OK\r\nCache-Control: no-cache, no-store\r\nContent-Type: application/json\r\nDate: Thu, 21 Nov 2024 17:22:43 GMT\r\nPragma: no-cache\r\nStrict-Transport-Security: max-age=15724800; includeSubDomains\r\nVary: Accept-Encoding\r\nX-Ratelimit-Limit: 200, 200;w=60\r\nX-Ratelimit-Remaining: 199\r\nX-Ratelimit-Reset: 17\r\n\r\n{\"app\":{\"id\":\"2635617b-9ed4-4491-a10e-3bcd18be5129\",\"name\":\"duckdb-spawn\",\"organization_id\":\"907de27c-acaa-4573-bf2a-3a7d34ce0baa\",\"created_at\":\"2024-11-21T17:22:42.595491Z\",\"updated_at\":\"2024-11-21T17:22:42.595491Z\",\"started_at\":null,\"succeeded_at\":null,\"paused_at\":null,\"resumed_at\":null,\"terminated_at\":null,\"status\":\"STARTING\",\"messages\":[\"App starting.\"],\"version\":\"0\",\"domains\":[{\"id\":\"6e23c8fb-9327-4e7e-ba6a-0b7524c0a58d\",\"organization_id\":\"907de27c-acaa-4573-bf2a-3a7d34ce0baa\",\"name\":\"duckdb-spawn-dealexmachina-b837970c.koyeb.app\",\"creat
time="2024-11-21T17:22:43Z" level=debug msg="========== HTTP request ==========\nPOST /v1/services HTTP/1.1\r\nHost: app.koyeb.com\r\nUser-Agent: koyeb-cli/5.3.0\r\nContent-Length: 371\r\nAccept: */*\r\nAuthorization: <HIDDEN, add --debug-full to show the token>\nContent-Type: application/json; charset=utf-8\r\nAccept-Encoding: gzip\r\n\r\n{\"app_id\":\"2635617b-9ed4-4491-a10e-3bcd18be5129\",\"definition\":{\"git\":{\"branch\":\"main\"},\"instance_types\":[{\"scopes\":[\"region:was\"],\"type\":\"nano\"}],\"name\":\"api\",\"ports\":[{\"port\":8000,\"protocol\":\"http\"}],\"regions\":[\"was\"],\"routes\":[{\"path\":\"/\",\"port\":8000}],\"scalings\":[{\"max\":1,\"min\":1,\"scopes\":[\"region:was\"],\"targets\":[]}],\"skip_cache\":false,\"strategy\":{},\"type\":\"WEB\"}}\n\n========== end of request ==========\n"
time="2024-11-21T17:22:43Z" level=debug msg="========== HTTP response ==========\nHTTP/2.0 400 Bad Request\r\nContent-Length: 150\r\nCache-Control: no-cache, no-store\r\nContent-Type: application/json\r\nDate: Thu, 21 Nov 2024 17:22:43 GMT\r\nPragma: no-cache\r\nStrict-Transport-Security: max-age=15724800; includeSubDomains\r\nX-Ratelimit-Limit: 30, 30;w=60\r\nX-Ratelimit-Remaining: 29\r\nX-Ratelimit-Reset: 17\r\n\r\n{\"status\":400,\"code\":\"invalid_argument\",\"message\":\"Validation error\",\"fields\":[{\"field\":\"definition.git.repository\",\"description\":\"cannot be blank\"}]}\n========== end of response ==========\n"
❌ Error while creating the service: the Koyeb API returned an error 400: Validation error
🔎 Additional details
Field definition.git.repository: cannot be blank
🏥 How to solve the issue?
Fix the request, and try again
🕦 The original error was:
400 Bad Request 
Error: Process completed with exit code 1.

On a variation note

I will try to use Pulumi in the action yaml to deploy to Koyeb.