Skip to content
Snippets Groups Projects
Traefik.php 5.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • jurgenhaas's avatar
    jurgenhaas committed
    <?php
    
    namespace LakeDrops\DockerTraefik;
    
    use Symfony\Component\Filesystem\Filesystem;
    use Symfony\Component\Yaml\Yaml;
    
    
    /**
     * Class Traefik.
     *
     * @package LakeDrops\DockerTraefik
     */
    
    jurgenhaas's avatar
    jurgenhaas committed
    class Traefik {
    
    
      /**
       * The name of the project using Traefik.
       *
       * @var string
       */
    
    jurgenhaas's avatar
    jurgenhaas committed
      protected $name;
    
    
      /**
       * @var string
       */
      protected $domain;
    
      /**
       * @var int
       */
      protected $http_port;
    
      /**
       * @var int
       */
      protected $https_port;
    
      /**
       * @var string
       */
      protected $cert_filename;
    
      /**
       * @var string
       */
      protected $key_filename;
    
    
      /**
       * @var bool
       */
      protected $addon_portainer = FALSE;
    
    
    jurgenhaas's avatar
    jurgenhaas committed
      /**
       * Traefik constructor.
       *
       * @param string $name
    
       *   Name of the network to be created which needs to match the container
       *   prefix of your project you would like to handle with Traefik.
    
       * @param string $domain
       *   The domain name used for all local projects.
       * @param int $http_port
       *   Port for non secure requests.
       * @param int $https_port
       *   Port for secure requests.
       * @param string $cert_filename
       *   Filename of the SSL certificate.
       * @param string $key_filename
       *   Filename of the private key for the SSL certificate.
    
    jurgenhaas's avatar
    jurgenhaas committed
       */
    
      public function __construct(string $name, $domain = 'docker.localhost', $http_port = 8000, $https_port = 8443, $cert_filename = 'fullchain.pem', $key_filename = 'privkey.pem') {
    
    jurgenhaas's avatar
    jurgenhaas committed
        $this->name = $name;
    
        $this->domain = $domain;
        $this->http_port = $http_port;
        $this->https_port = $https_port;
        $this->cert_filename = $cert_filename;
        $this->key_filename = $key_filename;
    
    jurgenhaas's avatar
    jurgenhaas committed
      }
    
    
      /**
       * @param bool $addon_portainer
       */
      public function setAddonPortainer(bool $addon_portainer): void {
        $this->addon_portainer = $addon_portainer;
      }
    
    
    jurgenhaas's avatar
    jurgenhaas committed
      /**
       * Update the Traefik container.
       */
    
      public function update(): void {
        // Update host wide traefik container.
    
    jurgenhaas's avatar
    jurgenhaas committed
        $traefikPath = $_SERVER['HOME'] . '/.traefik';
    
        $traefikCertPath = $_SERVER['HOME'] . '/.traefik/certs';
    
        $traefikConfigPath = $_SERVER['HOME'] . '/.traefik/configuration';
    
    jurgenhaas's avatar
    jurgenhaas committed
        $traefikFile = $traefikPath . '/docker-compose.yml';
    
    
        $fs = new Filesystem();
    
          $fs->mkdir($traefikPath);
    
    jurgenhaas's avatar
    jurgenhaas committed
        }
    
        if (!$fs->exists($traefikCertPath)) {
          $fs->mkdir($traefikCertPath);
        }
    
        if (!$fs->exists($traefikConfigPath)) {
          $fs->mkdir($traefikConfigPath);
        }
        file_put_contents($traefikConfigPath . '/certificates.toml', $this->defaultCertificatesConfig());
    
        file_put_contents($traefikFile, Yaml::dump($this->defaultDockerCompose(), 9, 2));
        $cwd = getcwd();
        chdir($traefikPath);
        exec('docker network create traefik-public 2>/dev/null');
        exec('docker compose --project-name traefik up -d');
        chdir($cwd);
    
    jurgenhaas's avatar
    jurgenhaas committed
      }
    
    
      /**
       * @return array
       */
      private function defaultDockerCompose(): array {
    
        $config = [
          'version' => '3.3',
    
              'command' => [
                '--api=true',
                '--api.dashboard=true',
                '--api.insecure=true',
    
                '--entrypoints.web.address=:80',
                '--entrypoints.websecure.address=:443',
    
                '--entrypoints.websecure.http.tls.domains[0].main=' . $this->domain,
                '--entrypoints.websecure.http.tls.domains[0].sans=.' . $this->domain,
                '--providers.file.directory=/configuration/',
                '--providers.file.watch=true',
                '--providers.docker=true',
                '--providers.docker.exposedbydefault=false',
              ],
              'restart' => 'unless-stopped',
              'networks' => [
    
              ],
              'ports' => [
                $this->http_port . ':80',
                $this->https_port . ':443',
              ],
              'labels' => [
                'traefik.enable=true',
    
                'traefik.http.routers.traefik.service=api@internal',
                'traefik.http.routers.traefik.rule=Host(`traefik.' . $this->domain . '`)',
              ],
              'volumes' => [
                './certs:/certs/:ro',
                './configuration:/configuration/:ro',
                '/var/run/docker.sock:/var/run/docker.sock:ro',
              ],
            ],
          ],
          'networks' => [
    
        if ($this->addon_portainer) {
          $config['services']['portainer'] = [
    
            'command' => '-H unix:///var/run/docker.sock',
            'restart' => 'unless-stopped',
            'networks' => [
    
            ],
            'labels' => [
              'traefik.enable=true',
    
              'traefik.http.routers.frontend.rule=Host(`portainer.' . $this->domain . '`)',
              'traefik.http.routers.frontend.entrypoints=websecure',
              'traefik.http.services.frontend.loadbalancer.server.port=9000',
              'traefik.http.routers.frontend.service=frontend',
              'traefik.http.routers.edge.rule=Host(`edge.' . $this->domain . '`)',
              'traefik.http.routers.edge.entrypoints=websecure',
              'traefik.http.services.edge.loadbalancer.server.port=8000',
              'traefik.http.routers.edge.service=edge',
            ],
            'volumes' => [
              './portainerdata:/data',
              '/var/run/docker.sock:/var/run/docker.sock:ro',
            ],
          ];
        }
        return $config;
    
      }
    
      /**
       * @return string
       */
      private function defaultCertificatesConfig(): string {
        return <<<EOF
    [[tls.certificates]]
       certFile = "/certs/$this->cert_filename"
       keyFile = "/certs/$this->key_filename"
    EOF;
    
      }
    
    
    jurgenhaas's avatar
    jurgenhaas committed
    }