Thibault Mocellin

Thibault Mocellin

Développeur Full-Stack freelance basé à Annecy 🇫🇷

Utilisation de Caddy Server avec Docker

Posted on February 19, 2019

Présentation

Caddy est un serveur web HTTP/2 avec une gestion de HTTPS automatique. Il permet de servir des fichiers statiques mais il peut aussi être utilisé comme reverse-proxy pour une application Node.js par exemple. De plus la configuration de ce dernier est très simple. Vous pouvez visiter cette page pour voir l’ensemble des fonctionnalités.

Dans cet article nous allons voir plusieurs exemples d’utilisation :

  • Utilisation pour un site statique.
  • Utilisation pour une application Node.js.
  • Utilisation pour un site statique qui communique avec une application Node.js

Nous verrons comment l’utiliser avec Docker, dans un environnement local mais aussi comment l’utiliser sur un serveur avec un domaine et le https.

Avant de commencer nous allons créer un dossier CaddySamples qui contiendra nos différents exemples :

mkdir CaddySamples

Utilisation pour un site statique

Commençons par le cas le plus basique l’utilisation du serveur web pour servir un site statique. Ajoutez un dossier static-website-sample :

mkdir static-website-sample

Dans cet exemple nous aurons trois fichiers :

  • docker-compose.yml : Le fichier de configuration de nos services docker.
  • Caddyfile : Le fichier de configuration de Caddy.
  • /src/index.html : La page web que nous souhaitons servir.

Ajoutez maintenant le fichier index.html dans le dossier src avec le contenu suivant :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>Caddy Web Server</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
    <script src="main.js"></script>
  </head>
  <body>
    <h1>Every Site on HTTPS</h1>
    <h2>Caddy is the HTTP/2 web server with automatic HTTPS.</h2>
    <iframe
      src="https://ghbtns.com/github-btn.html?user=mholt&amp;repo=caddy&amp;type=star&amp;count=true&amp;size=large"
      scrolling="0"
      class="github-stars"
      width="160px"
      height="30px"
      frameborder="0"
    ></iframe>
  </body>
</html>

Passons à la configuration de Caddy. Comme vous avez pu le constater juste au dessus la configuration de Caddy ce fait à l’aide d’un fichier nommé Caddyfile. Dans notre cas nous voulons pouvoir accéder au contenu de notre dossier src via notre serveur Caddy en local sur le port 80.

Créer le fichier Caddyfile et ajoutez la configuration suivante :

localhost:80

Ici notre fichier de configuration indique au serveur que nous souhaitons accéder au contenu du dossier root du serveur via localhost:80. L’image Docker que nous allons utiliser a pour dossier root le dossier /srv. Si vous n’utiliser pas docker ou une image différente vous pouvez spécifier le dossier root avec la configuration suivante :

localhost:80 {
    root /www/mysite.com
}

Maintenant il ne nous reste plus qu’à installer Caddy et le lancer pour ce faire nous allons utiliser Docker et docker-compose. L’image Docker de Caddy utilisé est celle-ci.

Ajoutez un fichier docker-compose.yml avec le contenu suivant :

version: '2'
services:
  server:
    image: abiosoft/caddy
    container_name: caddy
    ports:
      - '80:80'
    volumes:
      - './Caddyfile:/etc/Caddyfile'
      - './src:/srv'

Pour ce premier exemple nous pourrions nous passer de docker-compose et lancer directement le container avec docker mais cela va nous servir de base pour la suite.

Ici :

  1. On créer un service nomée server à partir de l’image abiosoft/caddy
  2. On map le port 80 du container avec celui de notre host
  3. On spécifie le fichier de configuration à utiliser via le volume './Caddyfile:/etc/Caddyfile'
  4. On map le dossier src qui contient notre page avec le dossier root du container qui est srv

Maintenant il n’y a plus qu’à lancer la commande :

docker-compose up

Et le HTTPS dans tous ça ?

Pour le HTTPS la configuration ne va pas changer beaucoup mais d’abord partons du principe que vous avez les éléments suivants :

  • un serveur (si vous en avez pas, vous pouvez utiliser ce lien qui vous donnera 100$ de crédits pour en créer un).
  • un domaine (pour notre exemple nous utiliserons exemple.com) et un sous-domaine (api.exemple.com).
  • Un enregistrement DNS qui fait pointer votre domaine et sous-domaine sur l’ip de votre serveur.

Si vous disposez de l’ensemble des prérequis alors la première chose à faire est de modifier le fichier de configuration Caddyfile comme ci-dessous :

exemple.com

Nous avons juste remplacer localhost:80 par le domaine sur lequel notre site sera accessible une fois déployé. Pour terminer nous modifions le fichier docker-compose.yml en ajoutant ces valeurs :

ports:
  - '80:80'
  - '443:443'
volumes:
  - './Caddyfile:/etc/Caddyfile'
  - './src:/srv'
  - './caddy:/root/.caddy'

Pour HTTPS il faut ajouter le mapage du port 443. Ensuite nous ajoutons un nouveaux volume qui va nous permettre de garder de manière persistante les certificats ssl générés par Caddy au lancement. Si nous n’ajoutons pas ce volume à chaque fois que le container sera recréé alors les certificats le seront aussi.

Utilisation pour une application Node.js

Maintenant nous allons passer à l’utilisation comme reverse-proxy pour une application Node.js.

Le but de cet article n’étant pas l’application Node en elle-même nous allons vite passer sur cette partie.

A la racinde du dossier CaddySamples créer un dossier node-js-sample et ajoutez-y un dossier api :

mkdir node-js-sample && cd node-js-sample
mkdir api && cd api

Ensuite dans le dossier api commencez par ajouter le fichier package.json :

{
  "name": "node_js_app",
  "version": "1.0.0",
  "description": "Node.js",
  "author": "Thibaut MOCELLIN",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.16.1"
  }
}

Puis un fichier server.js :

'use strict'

const express = require('express')

// Constants
const PORT = 3000
const HOST = '0.0.0.0'

// App
const app = express()
app.get('/', (req, res) => {
  res.send('Hello world node js\n')
})

app.listen(PORT, HOST)
console.log(`Running on http://${HOST}:${PORT}`)

Et enfin un fichier Dockerfile :

FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD [ "npm", "start" ]

Passons à la création du fichier docker-compose.yml ajoutez ce dernier dans le dossier node-js-sample :

version: '2'
services:
  api:
    build: ./api
    container_name: 'node-api'
    restart: always
    ports:
      - '3000:3000'
  server:
    image: abiosoft/caddy
    container_name: caddy
    ports:
      - '80:80'
    links:
      - api
    volumes:
      - './Caddyfile:/etc/Caddyfile'

Nous avons deux services :

  • api : Notre application Node construite à partir de notre Dockerfile.
  • server : Notre serveur web Caddy.

Maintenant vous pouvez ajouter le fichier Caddyfile :

localhost:80 {
  proxy /  api:3000
}

Ici nous indiquons à Caddy de rediriger les requêtes arrivant sur localhost:80 vers api:3000. api est le nom de notre service node-js dans le fichier docker-compose.yml.

Comme pour l’exemple précédent il ne vous reste plus qu’à lancer la commande :

docker-compose up

La mise en place de HTTPS se fait strictement de la même manière que l’exemple précédent.

Utilisation pour un site statique qui communique avec une application Node.js

Maintenant nous allons mettre en place les deux exemples précédents ensembles et les faire communiquer entre eux la page statique fera un apel http à notre api qui lui répondra.

La page statique sera accessible via localhost:80 (exemple.com) et l’api via localhost:8080 (api.exemple.com).

Pour ce faire dans le dossier CaddySamples créez un dossier static-website-and-node-sample ensuite ajoutez dedans un dossier web .

mkdir static-website-and-node-sample && cd static-website-and-node-sample
mkdir web

Dans le dossier web copiez le fichier index.html du premier exemple. Ensuite dans le dossier static-website-and-node-sample copier le dossier api de l’exemple précédent.

Maintenant nous allons modifier notre page html pour ajouter le script qui fera une requête http à notre api. Dans la page index.html ajoutez le script suivant avant la fin du body :

<div style="background-color:green" id="data"></div>
<script>
  fetch('http://localhost:8080/test')
    .then(data => {
      return data.json()
    })
    .then(jsonData => {
      var element = document.getElementById('data')
      element.innerHTML = JSON.stringify(jsonData)
      console.log(jsonData)
    })
    .catch(err => {
      alert(err)
    })
</script>

Puis nous ajoutons la route test à notre serveur dans le fichier server.js :

app.get('/test', (req, res) => {
  res.header('Access-Control-Allow-Origin', '*')
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
  res.send({ hello: 'world' })
})

Passons à la configuration du fichier Caddyfile :

localhost:80 {
}

localhost:8080 {
  proxy / api:3000
}

Ici on remarque que le fichier contient les configurations de chacun des exemples précédents.

Puis le fichier docker-compose.yml

version: '2'
services:
  api:
    build: ./api
    container_name: 'node-api'
    restart: always
    ports:
      - '3000:3000'
  server:
    image: abiosoft/caddy
    container_name: caddy
    ports:
      - '80:80'
      - '8080:8080'
    volumes:
      - './Caddyfile:/etc/Caddyfile'
      - './web:/srv'

Maintenant lorsque vous lancer vos services avec docker il seront respectivement disponnibles sur les ports 80 et 8080.

Voila nous avons vu une petite partie des fonctionnalités de Caddy Server.

Vous pouvez récupérer l’ensemble des exemples vu dans cet article en cliquant ici. Pour chacun des exemples vous trouverez un exemple avec localhost et un exemple avec le domaine exemple.com.

Partagez cet article si vous le souhaitez et si vous avez des questions vous pouvez me contacter par le chat.