diff --git a/__main__.py b/__main__.py
index 3877295..c81f6f9 100644
--- a/__main__.py
+++ b/__main__.py
@@ -3,102 +3,82 @@ import pulumi_docker as docker
import json
import os
-# Load the configuration from JSON file
+# Load the JSON configuration file
try:
with open("config.json", "r") as f:
containers_data = json.load(f)
- print("Loaded configuration from config.json successfully.")
-except FileNotFoundError as e:
- print(f"Error: {e}. The file 'config.json' was not found.")
- raise
-except json.JSONDecodeError as e:
- print(f"Error: {e}. There was an issue parsing 'config.json'.")
- raise
-except Exception as e:
- print(f"Unexpected error while loading config.json: {e}")
- raise
+except FileNotFoundError:
+ raise Exception("Error: 'config.json' file not found.")
-# Create the Docker network
+# Create the network
try:
network = docker.Network("testNetwork")
- print("Docker network 'testNetwork' created successfully.")
+ pulumi.export("network", network.name)
except Exception as e:
- print(f"Error creating Docker network: {e}")
- raise
+ pulumi.log.error(f"Failed to create network: {e}")
+ network = None
-# Create volumes for containers
+# Create volumes
volumes = {}
-for container in containers_data["containers"]:
+for container in containers_data.get("containers", []):
for volume in container.get("volumes", []):
- if "volume_name" in volume and volume["volume_name"] not in volumes:
- try:
+ try:
+ if "volume_name" in volume and volume["volume_name"] not in volumes:
volumes[volume["volume_name"]] = docker.Volume(volume["volume_name"])
- print(f"Volume {volume['volume_name']} created successfully.")
- except Exception as e:
- print(f"Error creating volume {volume['volume_name']}: {e}")
- raise
+ except Exception as e:
+ pulumi.log.error(f"Failed to create volume {volume.get('volume_name')}: {e}")
-# Create the containers
-for container in containers_data["containers"]:
+pulumi.export("volumes", {name: vol.name for name, vol in volumes.items()})
+
+# Create containers
+for container in containers_data.get("containers", []):
instances = container.get("instances", 1)
for i in range(instances):
container_name = f"{container['name']}-{i}" if instances > 1 else container["name"]
# Configure volumes
volumes_config = []
- for volume in container.get("volumes", []):
- try:
- if "volume_name" in volume:
- volumes_config.append(docker.ContainerVolumeArgs(
+ try:
+ if "volumes" in container:
+ volumes_config = [
+ docker.ContainerVolumeArgs(
container_path=volume["container_path"],
volume_name=volumes[volume["volume_name"]].name
- ))
- else:
- volumes_config.append(docker.ContainerVolumeArgs(
+ ) if "volume_name" in volume else
+ docker.ContainerVolumeArgs(
container_path=volume["container_path"],
host_path=os.path.abspath(volume["host_path"])
- ))
- print(f"Volume for container {container_name} configured successfully.")
- except Exception as e:
- print(f"Error configuring volume for container {container_name}: {e}")
- raise
+ )
+ for volume in container["volumes"]
+ ]
+ except KeyError as e:
+ pulumi.log.warn(f"Missing key in volume configuration: {e}")
+ except Exception as e:
+ pulumi.log.error(f"Error configuring volumes for container {container_name}: {e}")
- # Set entrypoint script (if any)
- entrypoint_script = "/entrypoint.sh" # Path where entrypoint.sh will be mounted
-
# Create the container
try:
- docker.Container(
+ container_resource = docker.Container(
container_name,
image=container["image"],
- envs=[f"{key}={value}" for key, value in container.get("envs", {}).items()],
- ports=[docker.ContainerPortArgs(
- internal=port["internal"],
- external=port["external"] + i
- ) for port in container.get("ports", [])],
- volumes=volumes_config + [
- # Mount the entrypoint.sh script into the container (if it exists)
- docker.ContainerVolumeArgs(
- container_path="/entrypoint.sh", # Path inside the container
- host_path=os.path.abspath("entrypoint.sh") # Path on the host machine
- )
- ] if "entrypoint.sh" in container.get("volumes", []) else [],
- network_mode=network.name,
- command=container.get("command", []) # Set the command from the JSON (if exists)
+ envs=[f"{key}={value}" for key, value in container.get("envs", {}).items()] if "envs" in container else [],
+ ports=[
+ docker.ContainerPortArgs(
+ internal=port["internal"],
+ external=port["external"] + i
+ ) for port in container.get("ports", [])
+ ] if "ports" in container else [],
+ volumes=volumes_config,
+ network_mode=network.name if network else None,
+ command=container.get("command", []),
)
- print(f"Container {container_name} created successfully.")
+ ports = container.get("ports", [])
+ if ports:
+ for port in ports:
+ external_port = port["external"] + i
+ pulumi.export(
+ f"{container_name}_url",
+ f"http://localhost:{external_port}"
+ )
except Exception as e:
- print(f"Error creating container {container_name}: {e}")
- raise
-
-# Export the container URLs
-urls = {}
-for container in containers_data["containers"]:
- for i in range(container.get("instances", 1)):
- container_name = f"{container['name']}-{i}" if container.get("instances", 1) > 1 else container["name"]
- for port in container.get("ports", []):
- if "external" in port:
- external_port = port["external"] + i
- urls[container_name] = f"http://localhost:{external_port}"
-
-pulumi.export("urls", urls)
\ No newline at end of file
+ pulumi.log.error(f"Failed to create container {container_name}: {e}")
diff --git a/config.json b/config.json
index 052d8c4..ec9b9e2 100644
--- a/config.json
+++ b/config.json
@@ -1,110 +1,90 @@
{
- "containers": [
- {
- "name": "db",
- "image": "postgres:latest",
- "envs": {
- "POSTGRES_DB": "admin",
- "POSTGRES_USER": "admin",
- "POSTGRES_PASSWORD": "admin"
- },
- "ports": [
- {"internal": 5432, "external": 5432}
- ],
- "volumes": [
- {
- "container_path": "/var/lib/postgresql/data",
- "volume_name": "postgres-data"
- }
- ]
+ "containers": [
+ {
+ "name": "db",
+ "image": "postgres:latest",
+ "envs": {
+ "POSTGRES_DB": "admin",
+ "POSTGRES_USER": "admin",
+ "POSTGRES_PASSWORD": "admin"
},
- {
- "name": "odoo-1",
- "image": "odoo:latest",
- "envs": {
- "HOST": "db",
- "USER": "admin",
- "PASSWORD": "admin",
- "DATABASE": "admin",
- "ODOO_PASSWORD": "admin"
- },
- "ports": [
- {"internal": 8069, "external": 8069},
- {"internal": 8070, "external": 8080}
- ],
- "instances": 1,
- "volumes": [
- {
- "container_path": "/entrypoint.sh",
- "host_path": "entrypoint.sh"
- }
- ]
+ "ports": [{"internal": 5432, "external": 5432}],
+ "volumes": [
+ {
+ "container_path": "/var/lib/postgresql/data",
+ "volume_name": "postgres-data"
+ }
+ ]
+ },
+ {
+ "name": "odoo",
+ "image": "odoo:latest",
+ "envs": {
+ "HOST": "db",
+ "USER": "admin",
+ "PASSWORD": "admin",
+ "DATABASE": "admin",
+ "ODOO_PASSWORD": "admin"
},
- {
- "name": "odoo-2",
- "image": "odoo:latest",
- "envs": {
- "HOST": "db",
- "USER": "admin",
- "PASSWORD": "admin",
- "DATABASE": "admin",
- "ODOO_PASSWORD": "admin"
- },
- "ports": [
- {"internal": 8069, "external": 8072},
- {"internal": 8071, "external": 8081}
- ],
- "instances": 1,
- "volumes": [
- {
- "container_path": "/entrypoint.sh",
- "host_path": "entrypoint.sh"
- }
- ]
+ "ports": [{"internal": 8069, "external": 8069}],
+ "instances": 2,
+ "command": ["/bin/bash", "-c", "sleep 10 && /opt/odoo/odoo-bin -i base"]
+ },
+ {
+ "name": "grafana",
+ "image": "grafana/grafana:latest",
+ "envs": {
+ "GF_SECURITY_ADMIN_PASSWORD": "grafana_pwd",
+ "GF_DATASOURCES_PROMETHEUS_URL": "http://prometheus:9090"
},
- {
- "name": "grafana",
- "image": "grafana/grafana:latest",
- "envs": {
- "GF_SECURITY_ADMIN_PASSWORD": "grafana_pwd",
- "GF_DATASOURCES_PROMETHEUS_URL": "http://prometheus:9090"
+ "ports": [{"internal": 3000, "external": 3000}],
+ "instances": 2
+ },
+ {
+ "name": "prometheus",
+ "image": "prom/prometheus:latest",
+ "ports": [{"internal": 9090, "external": 9090}],
+ "volumes": [
+ {
+ "container_path": "/prometheus",
+ "volume_name": "prometheus-data"
},
- "ports": [
- {"internal": 3000, "external": 3000}
- ],
- "instances": 2
+ {
+ "container_path": "/etc/prometheus/prometheus.yml",
+ "host_path": "./prometheus.yml"
+ }
+ ]
+ },
+ {
+ "name": "fluentd",
+ "image": "fluent/fluentd:v1.13-1",
+ "ports": [{"internal": 24224, "external": 24224}],
+ "volumes": [
+ {
+ "container_path": "/fluentd/etc/fluent.conf",
+ "host_path": "./fluent.conf"
+ }
+ ]
+ },
+ {
+ "name": "backup",
+ "image": "alpine:latest",
+ "envs": {
+ "POSTGRES_HOST": "db",
+ "POSTGRES_DB": "admin",
+ "POSTGRES_USER": "admin",
+ "POSTGRES_PASSWORD": "admin"
},
- {
- "name": "prometheus",
- "image": "prom/prometheus:latest",
- "envs": {
- "PROMETHEUS_STORAGE_TSDB_RETENTION": "15d"
- },
- "ports": [
- {"internal": 9090, "external": 9090}
- ],
- "volumes": [
- {
- "container_path": "/prometheus",
- "volume_name": "prometheus-data"
- }
- ]
- },
- {
- "name": "fluentd",
- "image": "fluent/fluentd:v1.13-1",
- "envs": {
- "FLUENTD_ARGS": "--no-supervisor"
- },
- "ports": [
- {"internal": 24224, "external": 24224}
- ],
- "volumes": [
- {
- "container_path": "/fluentd/log",
- "volume_name": "fluentd-log"
- }
- ]
- }
- ]
- }
\ No newline at end of file
+ "command": [
+ "/bin/sh", "-c",
+ "apk add --no-cache postgresql-client && sleep 10"
+ ],
+ "volumes": [
+ {
+ "container_path": "/backup",
+ "volume_name": "backup-data"
+ }
+ ]
+ }
+ ]
+}
diff --git a/entrypoint.sh b/entrypoint.sh
index ca17e95..a67d7e5 100644
--- a/entrypoint.sh
+++ b/entrypoint.sh
@@ -1,5 +1,10 @@
#!/bin/bash
set -e
-sleep 10
+
+until pg_isready -h db -U admin; do
+ echo "Waiting for PostgreSQL to be ready..."
+ sleep 10
+done
+
odoo -i base
-exec "$@"
\ No newline at end of file
+exec "$@"
diff --git a/fluent.conf b/fluent.conf
new file mode 100644
index 0000000..e9eadfa
--- /dev/null
+++ b/fluent.conf
@@ -0,0 +1,24 @@
+
+ @type forward
+ port 24224 # Fluentd default forward port
+ bind 0.0.0.0
+
+
+
+ @type forward
+ port 8069 # Odoo logs
+ bind 0.0.0.0
+
+
+
+ @type forward
+ port 3000 # Grafana logs
+ bind 0.0.0.0
+
+
+
+
+ @type stdout
+
+
+
diff --git a/prometheus.yml b/prometheus.yml
new file mode 100644
index 0000000..8fd6e99
--- /dev/null
+++ b/prometheus.yml
@@ -0,0 +1,20 @@
+global:
+ scrape_interval: 15s
+
+scrape_configs:
+ - job_name: 'postgres'
+ static_configs:
+ - targets: ['db:5432']
+
+ - job_name: 'odoo'
+ static_configs:
+ - targets: ['odoo-0:8069', 'odoo-1:8069']
+
+ - job_name: 'grafana'
+ static_configs:
+ - targets: ['grafana:3000']
+
+ - job_name: 'fluentd'
+ static_configs:
+ - targets: ['fluentd:24224']
+
\ No newline at end of file