# Préparer ton image

> Ce qu’Arkya attend d’une image Docker - écouter sur PORT, ne rien garder sur place, s’arrêter proprement, tourner sans privilèges. Avec des Dockerfile qui marchent.

Source : https://docs.arkya.gg/applications/image

Une application Arkya fait tourner ton image telle quelle. Quatre règles suffisent pour qu’elle démarre du premier coup.

## 1. Écouter sur PORT

Arkya pose la variable `PORT` au démarrage. Ton serveur doit écouter sur ce port, et sur `0.0.0.0` : `127.0.0.1` ne sort pas du conteneur.

Le port se choisit à la création de l’application dans l’espace client, et ne change plus ensuite. Une application créée avec `ark init` écoute sur `8080`.

```js server.js
const port = Number(process.env.PORT ?? 8080);
app.listen(port, "0.0.0.0");
```

## 2. Ne rien garder sur place

Une application n’a pas de disque. À chaque déploiement et à chaque redémarrage, elle repart de ton image : ce qu’elle a écrit entre-temps est perdu.

Tu peux écrire des fichiers temporaires, un cache par exemple. Tout ce qui doit durer va dans une [base de données](https://docs.arkya.gg/bases-de-donnees) du projet, ou dans un stockage externe : comptes, sessions, fichiers envoyés par tes utilisateurs.

## 3. S’arrêter proprement

Pour arrêter ou remplacer ton application, Arkya envoie le signal `SIGTERM`, puis coupe le conteneur 30 secondes plus tard. Ferme tes connexions à ce signal.

Si ton image démarre par un script shell, termine-le par `exec` : ton serveur reçoit alors le signal lui-même.

```bash
#!/bin/sh
node migrate.js
exec node server.js
```

## 4. Tourner sans privilèges

Le conteneur tourne sans mode privilégié, avec des capacités Linux réduites, et sans élévation possible : `sudo` et les programmes setuid n’y servent à rien.

Installe tes paquets pendant la construction : ce qu’un script ajoute au démarrage disparaît au redémarrage suivant. Et préfère un utilisateur sans droits dans ton `Dockerfile`, avec `USER`.

## Des Dockerfile qui marchent

**Node.js**

```dockerfile Dockerfile
FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
USER node
CMD ["node", "server.js"]
```

**Python**

```dockerfile Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
USER nobody
CMD ["sh", "-c", "exec gunicorn --bind 0.0.0.0:$PORT app:app"]
```

**Site statique**

```dockerfile Dockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine
RUN npm install -g serve@14
COPY --from=build /app/dist /site
USER node
CMD ["sh", "-c", "exec serve -s /site -l tcp://0.0.0.0:$PORT"]
```

## L’architecture

Les nœuds d’Arkya sont en `linux/amd64`. `ark build` construit pour eux, même depuis un Mac Apple Silicon. Si tu construis toi-même, ajoute `--platform linux/amd64` à `docker build`.

Une image construite pour une autre architecture s’arrête au démarrage avec `exec format error` dans le journal.

## L’analyse de sécurité

Chaque image envoyée au registre est analysée. Le verdict s’affiche dans `ark push` et dans l’onglet **Versions** de l’application.

- **Bloquée** : une faille critique ou élevée touche ce qui isole les conteneurs entre eux (noyau, `runc`, `containerd`, `sudo`, `util-linux`…). Cette version ne peut pas être mise en service.
- **Avertie** : des failles critiques ou élevées, qui ne touchent que ton application. La mise en service suit son cours.
- **Rien à signaler** : aucune faille critique ni élevée.

Les images Debian complètes, comme `node:22` ou `python:3.12`, embarquent souvent des paquets `linux-*` qui les font bloquer. Pars d’une variante `-slim` ou `-alpine`, et mets les paquets à jour pendant la construction.

## Essayer en local

```bash
docker build -t mon-api .
docker run --rm -e PORT=8080 -p 8080:8080 mon-api
```

Si `curl http://localhost:8080` répond, ton image écoute bien sur `PORT`. Si `docker stop` l’arrête en quelques secondes, elle gère `SIGTERM`.

## Une commande de démarrage différente

Le champ `start` du manifeste, ou `ark command`, remplace la commande de ton image. Elle est lancée par `/bin/sh -c` : ton image doit contenir un shell, ce qui exclut les images « distroless ». Voir [Le manifeste arkya.json](https://docs.arkya.gg/applications/manifeste).
