Brewless Brewless Docs

Running your application

Services

Run a service of your own next to the application, on an image you build, reached by the application with a secret only the two hold.

On this page

Some applications need a program next to them that is not PHP: a model that recognises names in text, a converter, a search engine. A service runs it in a container of its own, in the same Scaleway project and region as the application.

In brewless.yml

Name the service under the environment, with the directory that holds its Dockerfile:

brewless.yml
environments:
  production:
    services:
      gliner:
        build: services/gliner
        memory: 4096
        cpu: 2240
        timeout: 300
        min: 0
        max: 5
        concurrency: 2

A service name has lowercase letters and digits, starts with a letter and has no dashes; web, release and worker are taken. Without sizes a service gets 1024 MB, 560 thousandths of a vCPU, a timeout of 60 seconds and at most one replica, and it sleeps when nobody calls it (min: 0). See brewless.yml for the bounds.

Scaling

A service scales like the web container: Scaleway starts replicas as requests come in, between min and max. concurrency is how many requests one replica takes at once before Scaleway starts another (1 to 80). Without it a container Brewless made keeps Scaleway's own number, 50, so parallel requests wait on one replica. Set it to what one replica handles at the same time: a service with two worker processes takes concurrency: 2, and with max: 5 ten requests run side by side on five replicas. min: 0 lets the service sleep when nobody calls it; min: 1 keeps one replica warm, which costs while it runs.

Putting it live

brewless service:push production gliner

This builds the Dockerfile with Docker on your own machine, for linux/amd64, and uploads the image straight into a private bucket of your Scaleway project. A job in that project pushes it into your project's own registry, and Brewless makes the container gliner next to the web container, or gives the one there the new image. The image is never public and never passes through Brewless. The same image is not pushed twice: its tag is the identifier Docker gave it.

The container listens on the port in the PORT variable (8080). Brewless gives it one more variable, SERVICE_TOKEN: a secret it makes once in your Secret Manager and never replaces. The service has to refuse every request that does not carry it.

Note

Brewless does not build services in your project, as it does your application: a job there runs without privileges and cannot run a Dockerfile. That is why the image of a service is built where Docker is: on your machine.

How the application reaches it

The next deploy gives the web, release and worker containers two variables per service: GLINER_URL, the address of the service's container, and GLINER_TOKEN, the same secret the service holds. Send the secret with every call, for example as Authorization: Bearer <GLINER_TOKEN>. The application calls the service directly; Brewless is not in between.

A deploy is refused while brewless.yml names a service that does not run yet: push it first. The variables go next to the environment's own variables, so a deploy with a service also needs those kept through Brewless (push them once with brewless env:push).

Changing the sizes or the scaling of a service in brewless.yml takes effect at the next brewless service:push, also when the image did not change: the container gets the new settings. A deploy of the application does not change them. brewless plan shows them next to what the container has, marked as applied by brewless service:push. Taking a service out of the file stops the application getting its variables at the next deploy; the container itself keeps running until you remove it in your Scaleway console.

A private service

By default a service's container has a public address, like every Serverless Container: anyone who knows it can send a request, and only the secret keeps them out. private: true takes that address away:

brewless.yml
environments:
  production:
    network: private
    services:
      gliner:
        build: services/gliner
        private: true

At brewless service:push the container joins the project's Private Network (see A Private Network), gets a private endpoint on it, and its default public endpoint is switched off: from the internet its address answers 404, with or without the secret. The application then reaches it on the private endpoint, which Scaleway names http://<container id>.<network id>.internal, and the next deploy gives that address as GLINER_URL. The secret stays: send it as before.

  • A private service needs network: private (or a cache) on its environment: the web, release and worker containers have to be on the same network to reach it. Without it the file is refused.
  • The push is refused while one of those containers is not on the network yet. Deploy once with network: private first, so they join it.
  • Between the push and the next deploy the application still holds the old public address, which no longer answers. Deploy right after the push.
  • The private endpoint speaks HTTP inside the network. HTTPS on it needs Scaleway's own certificate authority in the application.
  • Taking private: true out again and pushing gives the container its public address back; it stays on the network.