Added support for swarm mode.
This commit is contained in:
parent
2655c76fe6
commit
428f477ba3
5 changed files with 172 additions and 50 deletions
|
|
@ -1,4 +1,4 @@
|
|||
FROM benzine/php:cli-8.0
|
||||
FROM benzine/php:cli-8.0 as bouncer
|
||||
LABEL maintainer="Matthew Baggett <matthew@baggett.me>" \
|
||||
org.label-schema.vcs-url="https://github.com/benzine-framework/docker" \
|
||||
org.opencontainers.image.source="https://github.com/benzine-framework/docker"
|
||||
|
|
@ -47,4 +47,11 @@ COPY bouncer /app
|
|||
COPY composer.* /app/
|
||||
RUN composer install && \
|
||||
chmod +x /app/bouncer && \
|
||||
mkdir -p /var/log/bouncer
|
||||
mkdir -p /var/log/bouncer
|
||||
|
||||
FROM benzine/php:nginx-8.0 as test-app-a
|
||||
COPY ./test/public-web-a /app/public
|
||||
|
||||
FROM benzine/php:nginx-8.0 as test-app-b
|
||||
COPY ./test/public-web-b /app/public
|
||||
|
||||
|
|
|
|||
37
bouncer/Makefile
Normal file
37
bouncer/Makefile
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
test-as-service: clean
|
||||
docker build -t bouncer --target bouncer .
|
||||
docker build -t test-app-a --target test-app-a .
|
||||
docker build -t test-app-b --target test-app-b .
|
||||
-docker network create --driver overlay bouncer-test
|
||||
$(MAKE) start_bouncer
|
||||
$(MAKE) start_test_a
|
||||
$(MAKE) start_test_b
|
||||
docker service logs -f bouncer
|
||||
start_test_a:
|
||||
docker service create \
|
||||
--network bouncer-test \
|
||||
--name test-app-a \
|
||||
--env BOUNCER_DOMAIN=test-a.local \
|
||||
--env BOUNCER_ALLOW_NON_SSL=yes \
|
||||
--publish 8081:80 \
|
||||
test-app-a
|
||||
start_test_b:
|
||||
docker service create \
|
||||
--network bouncer-test \
|
||||
--name test-app-b \
|
||||
--env BOUNCER_DOMAIN=test-b.local \
|
||||
--env BOUNCER_ALLOW_NON_SSL=yes \
|
||||
--publish 8082:80 \
|
||||
test-app-b
|
||||
start_bouncer:
|
||||
docker service create \
|
||||
--network bouncer-test \
|
||||
--name bouncer \
|
||||
--publish 8080:80 \
|
||||
--mount type=bind,destination=/var/run/docker.sock,source=/var/run/docker.sock \
|
||||
bouncer
|
||||
|
||||
clean:
|
||||
-docker service rm bouncer test-app-a test-app-b
|
||||
#-docker network rm bouncer-test
|
||||
#-docker image rm test-app-a test-app-b bouncer
|
||||
124
bouncer/bouncer
124
bouncer/bouncer
|
|
@ -162,6 +162,25 @@ class Bouncer
|
|||
private Logger $logger;
|
||||
private string $instanceStateHash = '';
|
||||
private array $fileHashes;
|
||||
private bool $swarmMode = false;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSwarmMode(): bool
|
||||
{
|
||||
return $this->swarmMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $swarmMode
|
||||
* @return Bouncer
|
||||
*/
|
||||
public function setSwarmMode(bool $swarmMode): Bouncer
|
||||
{
|
||||
$this->swarmMode = $swarmMode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
@ -220,9 +239,10 @@ class Bouncer
|
|||
*
|
||||
* @return BouncerTarget[]
|
||||
*/
|
||||
public function findContainers(): array
|
||||
public function findContainersContainerMode(): array
|
||||
{
|
||||
$bouncerTargets = [];
|
||||
|
||||
$containers = json_decode($this->client->request('GET', 'containers/json')->getBody()->getContents(), true);
|
||||
foreach ($containers as $container) {
|
||||
$envs = [];
|
||||
|
|
@ -241,31 +261,7 @@ class Bouncer
|
|||
$bouncerTarget = (new BouncerTarget())
|
||||
->setId($inspect['Id'])
|
||||
;
|
||||
foreach ($envs as $eKey => $eVal) {
|
||||
switch ($eKey) {
|
||||
case 'BOUNCER_DOMAIN':
|
||||
$domains = explode(',', $eVal);
|
||||
array_walk($domains, function (&$domain, $key): void { $domain = trim($domain); });
|
||||
$bouncerTarget->setDomains($domains);
|
||||
|
||||
break;
|
||||
|
||||
case 'BOUNCER_LETSENCRYPT':
|
||||
$bouncerTarget->setLetsEncrypt(in_array(strtolower($eVal), ['yes', 'true'], true));
|
||||
|
||||
break;
|
||||
|
||||
case 'BOUNCER_TARGET_PORT':
|
||||
$bouncerTarget->setPort($eVal);
|
||||
|
||||
break;
|
||||
|
||||
case 'BOUNCER_ALLOW_NON_SSL':
|
||||
$bouncerTarget->setAllowNonSSL(in_array(strtolower($eVal), ['yes', 'true'], true));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
$bouncerTarget = $this->parseContainerEnvironmentVariables($envs, $bouncerTarget);
|
||||
|
||||
if (isset($inspect['NetworkSettings']['IPAddress']) && !empty($inspect['NetworkSettings']['IPAddress'])) {
|
||||
// As per docker service
|
||||
|
|
@ -282,6 +278,38 @@ class Bouncer
|
|||
$bouncerTargets[] = $bouncerTarget;
|
||||
}
|
||||
}
|
||||
return $bouncerTargets;
|
||||
}
|
||||
public function findContainersSwarmMode(): array
|
||||
{
|
||||
$bouncerTargets = [];
|
||||
$services = json_decode($this->client->request('GET', 'services')->getBody()->getContents(), true);
|
||||
|
||||
if(isset($services['message'])){
|
||||
$this->logger->debug(sprintf('Something happened while interrogating services.. This node is not a swarm node, cannot have services: %s', $services['message']));
|
||||
}else{
|
||||
foreach($services as $service){
|
||||
$envs = [];
|
||||
foreach($service['Spec']['TaskTemplate']['ContainerSpec']['Env'] as $env){
|
||||
list($eKey, $eVal) = explode("=", $env,2);
|
||||
$envs[$eKey] = $eVal;
|
||||
}
|
||||
if(isset($envs['BOUNCER_DOMAIN'])) {
|
||||
$bouncerTarget = (new BouncerTarget())
|
||||
->setId($service['ID']);
|
||||
|
||||
$bouncerTarget = $this->parseContainerEnvironmentVariables($envs, $bouncerTarget);
|
||||
|
||||
$bouncerTarget->setIp("172.17.0.1");
|
||||
$bouncerTarget->setPort($service['Endpoint']['Ports'][0]['PublishedPort']);
|
||||
$bouncerTarget->setTargetPath(sprintf('http://%s:%d/', $bouncerTarget->getIp(), $bouncerTarget->getPort()));
|
||||
|
||||
$this->logger->debug(sprintf('Decided that %s has the target path %s', $bouncerTarget->getName(), $bouncerTarget->getTargetPath()));
|
||||
|
||||
$bouncerTargets[] = $bouncerTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bouncerTargets;
|
||||
}
|
||||
|
|
@ -335,7 +363,11 @@ class Bouncer
|
|||
if ($this->s3Enabled()) {
|
||||
$this->getCertificatesFromS3();
|
||||
}
|
||||
$targets = $this->findContainers();
|
||||
$determineSwarmMode = json_decode($this->client->request('GET', 'swarm')->getBody()->getContents(), true);
|
||||
$this->setSwarmMode(!isset($determineSwarmMode['message']));
|
||||
$this->logger->info(sprintf("Swarm mode is %s.", $this->isSwarmMode() ? 'enabled' : 'disabled'));
|
||||
$targets = $this->isSwarmMode() ? $this->findContainersSwarmMode() : $this->findContainersContainerMode();
|
||||
|
||||
$this->logger->info(sprintf('%s Found %d services with BOUNCER_DOMAIN set', Emoji::CHARACTER_MAGNIFYING_GLASS_TILTED_LEFT, count($targets)));
|
||||
foreach ($targets as $target) {
|
||||
$this->generateNginxConfig($target);
|
||||
|
|
@ -494,6 +526,44 @@ class Bouncer
|
|||
$this->logger->info(sprintf('%s Restarting nginx', Emoji::CHARACTER_TIMER_CLOCK));
|
||||
$shell->run($command);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $envs
|
||||
* @param BouncerTarget $bouncerTarget
|
||||
* @return BouncerTarget
|
||||
*/
|
||||
public function parseContainerEnvironmentVariables(array $envs, BouncerTarget $bouncerTarget): BouncerTarget
|
||||
{
|
||||
foreach ($envs as $eKey => $eVal) {
|
||||
switch ($eKey) {
|
||||
case 'BOUNCER_DOMAIN':
|
||||
$domains = explode(',', $eVal);
|
||||
array_walk($domains, function (&$domain, $key): void {
|
||||
$domain = trim($domain);
|
||||
});
|
||||
$bouncerTarget->setDomains($domains);
|
||||
|
||||
break;
|
||||
|
||||
case 'BOUNCER_LETSENCRYPT':
|
||||
$bouncerTarget->setLetsEncrypt(in_array(strtolower($eVal), ['yes', 'true'], true));
|
||||
|
||||
break;
|
||||
|
||||
case 'BOUNCER_TARGET_PORT':
|
||||
$bouncerTarget->setPort($eVal);
|
||||
|
||||
break;
|
||||
|
||||
case 'BOUNCER_ALLOW_NON_SSL':
|
||||
$bouncerTarget->setAllowNonSSL(in_array(strtolower($eVal), ['yes', 'true'], true));
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return $bouncerTarget;
|
||||
}
|
||||
}
|
||||
|
||||
(new Bouncer())->run();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
echo "Starting Bouncer"
|
||||
/app/bouncer
|
||||
sleep 60;
|
||||
sleep 30;
|
||||
|
|
@ -2,36 +2,44 @@ version: "3.4"
|
|||
|
||||
services:
|
||||
bouncer:
|
||||
image: benzine/bouncer
|
||||
build: .
|
||||
image: bouncer
|
||||
build:
|
||||
context: .
|
||||
target: bouncer
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./:/app
|
||||
environment:
|
||||
- BOUNCER_LETSENCRYPT_MODE=staging
|
||||
- BOUNCER_LETSENCRYPT_EMAIL=matthew@baggett.me
|
||||
- BOUNCER_S3_ENDPOINT=http://grey.ooo:9000
|
||||
- BOUNCER_S3_KEY_ID=geusebio
|
||||
- BOUNCER_S3_KEY_SECRET=changeme
|
||||
- BOUNCER_S3_BUCKET=bouncer-certificates
|
||||
- BOUNCER_S3_USE_PATH_STYLE_ENDPOINT="yes"
|
||||
# environment:
|
||||
# - BOUNCER_LETSENCRYPT_MODE=staging
|
||||
# - BOUNCER_LETSENCRYPT_EMAIL=matthew@baggett.me
|
||||
# - BOUNCER_S3_ENDPOINT=http://grey.ooo:9000
|
||||
# - BOUNCER_S3_KEY_ID=geusebio
|
||||
# - BOUNCER_S3_KEY_SECRET=changeme
|
||||
# - BOUNCER_S3_BUCKET=bouncer-certificates
|
||||
# - BOUNCER_S3_USE_PATH_STYLE_ENDPOINT="yes"
|
||||
ports:
|
||||
- 127.0.99.100:80:80
|
||||
- 127.0.99.100:443:443
|
||||
|
||||
web-a:
|
||||
image: benzine/php:nginx
|
||||
image: test-app-a
|
||||
build:
|
||||
context: .
|
||||
target: test-app-a
|
||||
volumes:
|
||||
- ./test/public-web-a:/app/public
|
||||
environment:
|
||||
- BOUNCER_DOMAIN=a.web.grey.ooo
|
||||
- BOUNCER_LETSENCRYPT=true
|
||||
# - BOUNCER_LETSENCRYPT=true
|
||||
|
||||
web-b:
|
||||
image: test-app-b
|
||||
build:
|
||||
context: .
|
||||
target: test-app-b
|
||||
volumes:
|
||||
- ./test/public-web-b:/app/public
|
||||
environment:
|
||||
- BOUNCER_DOMAIN=b.web.grey.ooo
|
||||
# - BOUNCER_LETSENCRYPT=true
|
||||
|
||||
# web-b:
|
||||
# image: benzine/php:nginx
|
||||
# volumes:
|
||||
# - ./test/public-web-b:/app/public
|
||||
# environment:
|
||||
# - BOUNCER_DOMAIN=b.web.grey.ooo
|
||||
#
|
||||
#
|
||||
Loading…
Reference in a new issue