Can GPT5 / Claude Sonet replace me and my team ?
Seems to be the question on everyones mind lately. Well can they really ?. Let's find out shall we ?
Spoiler alert, the answer is not a simple YES or NO.
Vibe Coding
Lets gets some things clarified. I'm not vibe coding here. I have strong opinions about the pitfalls of vibe coding in production systems. This is not the place to discuss that. I don't exactly know what to call this but to put things simply I'm using AI with well defined context to do this experiment.
Credits
This project is based on Ed Donner's CrewAI project featured in The Complete AI Engineering Course, If you are interested in learning more you should check out the learning material by Ed Donner. I highly recommend them.
The Project
In order to test out this hypothesis I'm gonna use Crew AI . The title was a catchy one, the project however has a narrower context. I'm not trying to create an AI Engineering team to replace us humans, rather experimenting to see how we can use AI to boost our productivity.
The problem I have chosen, I believe is not too complex, not too simple. This will allow me to analyze the results easily and get a good baseline for further experimentation.
The task is to get a containerized solution up and running to a provided problem statement. Which is classified as an "assignment" in the below config. We'll go into details when analyzing the two different approaches.
Task Definitions
design_task:
description: >
Create a solution determining what docker images can be used to solve the {assignment}
Follow docker and docker compose best practices
IMPORTANT: Output ONLY the raw markdown without any markdown formatting, code block delimiters, or backticks.
the current year is {current_year}.
expected_output: >
A docker compose file to do the {assignment}
agent: senior_engineer
output_file: output/design.md
coding_task:
description: >
Create a docker compose file that implements the design described by senior_engineer, in order to achieve the requirements.
Here are the requirements: {assignment}
Follow docker and docker compose best practices
IMPORTANT: Output ONLY the raw docker compose code without any markdown formatting, code block delimiters, or backticks.
the current year is {current_year}.
expected_output: >
A docker compose file to do the {assignment}
agent: docker_engineer
context:
- design_task
output_file: output/docker-compose.yml
documentation_task:
description: >
Create a readme.md markdown file explaining the docker compose file and how to run it
IMPORTANT: Output ONLY the raw markdown code without any markdown formatting, code block delimiters, or backticks.
the current year is {current_year}.
expected_output: >
A readme.md file explaining the solution and how to run it
agent: docker_engineer
context:
- coding_task
output_file: output/readme.md
Give me the details, gimme, gimme
I try two different approaches in this experiment. The first approach is to use a human senior engineer with an AI engineer to build the system. The human senior engineer is going to provide very prescriptive instructions for the AI engineer to complete the task in hand.
In the second approach we are going to use two different AI agents. One senior engineer which we will equip with design capabilities. We are gonna provide this agent with a problem statement with some guidelines. Then this senior AI agent is going to create the prescriptive instructions that will be used by the same AI engineer from the pervious example to produce the code.
Models Used
I tried using different models to try out this concept
- Claude Sonet 4 (claude-sonnet-4-20250514) by Anthropic
- gpt-4.1 by OpenAI
- gpt5 by OpenAI
- deepseek-chat by DeepSeek
- llama3.2 by Meta hosted with Ollama locally
Human Senior Engineer with an AI Engineering team
In the first approach we have a human senior engineer providing the detailed instructions to the AI engineering team. The senior engineer is going to provide a very prescriptive task for the AI engineers
assignment = f"""Created a self hosted nextcloud instance. Use the docker hub image nextcloud:31.0.8-apache
use mariadb:10.11 as the database
use redis:alpine3.22 with nextcloud
create separate containers for nextcloud and cron jobs
Use jc21/nginx-proxy-manager:latest as a reverse proxy to expose the nextcloud instance to the internet
# """
AI Senior Engineer with an AI Engineering Team
In the second approach the senior engineer is also replaced by an AI Agent. We provide the problem statement to the AI Senior Engineering Agent. This agent in turn is gonna provide a prescriptive task for the crew to generate the output
assignment = f"""Created a self hosted nextcloud instance.
Think about separation of concerns, maintainability and other software development best practices
The instance needs to be exposed to the internet
The same server that is going to host the nextcloud instance also has some simple websites exposed to the internet
The nextcloud instance and the other websites need their own ssl certificates
The server hosting all these is behind a pfsense firewall
"""
Agent Definitions
senior_engineer:
role: >
Engineer with extensive knowledge about software development practices including web based security vulnerabilities
goal: >
Provide solutions for complex software problems
backstory: >
You're a tenured engineer with extensive knowledge about software engineering
You are able to create software designs that can guide other engineers in creating solutions
llm: anthropic/claude-sonnet-4-20250514
docker_engineer:
role: >
Engineer with extensive knowledge about docker and docker compose
goal: >
Generate docker compose files with explanations
backstory: >
You're a tenured engineer with extensive knowledge about docker and docker compose.
You are able to create working docker compose files following best practices to fulfill the given requirements.
llm: anthropic/claude-sonnet-4-20250514Output and Conclusions
To be honest this exercise is too narrow and simplistic to come to a concrete conclusion. It does show some good data points though. (Full outputs in appendix)
When it comes to agents I was not able to produce good results with deepseek-chat or llama3.2. Only the frontier models were able to provide good enough data points in this project.
The first approach created a good simple working solution sticking with the provided guidelines. The second approach created a novel solution which could be classified as overkill. Though on second thought narrowing down the requirements to specify the host environment would have generated better results.
Some interesting observations include,
When acting as the Senior Engineer GPT 4.1 choose to use NGINX as the proxy where as GPT5 choose to use Traefik. According to Gemini, Traefik is more suitable for dynamic environments like Docker and Kubernetes. For the simple task definition NGINX would have been acceptable but I can't argue with using Traefik either. The problem statement didn't have enough information about the future extensibility or the available resourcing to lean towards one vs the other.
As the senior engineer GPT5 choose to use Postgress for the database where GPT 4.1 used MariaDB. The decision between these 2 also is a hard one. If you are curious read more here
In my opinion, both these decision differences indicate GPT5 chose the more modern options than GPT 4.1 in this particular problem. It could simply be due to the training data.
Claude Sonet 4 failed to act as the senior engineer for my project. It kept giving me "{type:error,error:{type:overloaded_error,message:Overloaded},request_id:null}". I see this error often when I try to do tasks needing more tokens. This I believe is due to the basic plan I'm paying for, not due to the capabilities of the Model.
DeepSeek-Chat hallucinated and returned a template project. Llama 3.2 failed as well. Indicating I'm trying to do too much with them.
When working with a human senior engineer the results were very similar across all frontier models.
Check out the appendix section for detailed outputs.
Conclusion
Well, AI has been a force multiplier when it comes to increasing my productivity. I'm not sold on the fact that AI will be able to completely replace us, however it sure is allowing us to do more with less. How that will pan out, only time will tell.
I'm excited for the future. What mistakes we will create vibe coding, what we will learn from those mistakes. Potential innovations we will see with responsible AI usage.... etc... etc...
Appendix
GPT 4.1 output (ai senior engineer)
version: "3.9"
services:
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:2.11.2
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "81:81"
volumes:
- npm_data:/data
- npm_letsencrypt:/etc/letsencrypt
environment:
- TZ=UTC
networks:
- frontend
db:
image: mariadb:11
container_name: nextcloud-db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
environment:
- MYSQL_ROOT_PASSWORD=secure_root_password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=secure_nextcloud_password
volumes:
- db_data:/var/lib/mysql
networks:
- backend
nextcloud:
image: nextcloud:28
container_name: nextcloud-app
restart: unless-stopped
expose:
- "80"
environment:
- MYSQL_PASSWORD=secure_nextcloud_password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_HOST=db
volumes:
- nextcloud_data:/var/www/html
depends_on:
- db
networks:
- frontend
- backend
web1:
image: nginx:1.25
container_name: simple-web1
restart: unless-stopped
volumes:
- ./web1/html:/usr/share/nginx/html:ro
- ./web1/nginx.conf:/etc/nginx/nginx.conf:ro
expose:
- "80"
networks:
- frontend
web2:
image: nginx:1.25
container_name: simple-web2
restart: unless-stopped
volumes:
- ./web2/html:/usr/share/nginx/html:ro
- ./web2/nginx.conf:/etc/nginx/nginx.conf:ro
expose:
- "80"
networks:
- frontend
volumes:
npm_data:
npm_letsencrypt:
db_data:
nextcloud_data:
networks:
frontend:
driver: bridge
backend:
driver: bridge
GPT 5 output (ai senior engineer)
name: selfhosted-apps
# Compose Specification (no version field needed in modern Compose)
# Requirements before use:
# - Create a .env file with:
# TRAEFIK_ACME_EMAIL=you@example.com
# NEXTCLOUD_DOMAIN=cloud.example.com
# SITE1_DOMAIN=site1.example.com
# SITE2_DOMAIN=site2.example.com
# - Create secrets/nextcloud_db_password.txt with a strong DB password
# - On pfSense: port-forward TCP 80 and 443 to this Docker host
# - Ensure DNS A/AAAA records for all domains point to your public IP
services:
# Reverse proxy and TLS termination with automatic per-domain certificates
traefik:
image: traefik:v3.1
command:
- --providers.docker=true
- --providers.docker.endpoint=tcp://docker-socket-proxy:2375
- --providers.docker.exposedbydefault=false
- --providers.docker.network=proxy
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entryPoint.to=websecure
- --entrypoints.web.http.redirections.entryPoint.scheme=https
- --entrypoints.websecure.address=:443
- --certificatesresolvers.letsencrypt.acme.email=${TRAEFIK_ACME_EMAIL}
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge=true
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
- --log.level=INFO
- --accesslog=true
ports:
- 80:80
- 443:443
volumes:
- traefik_letsencrypt:/letsencrypt
networks:
- proxy
- dockerproxy
depends_on:
- docker-socket-proxy
# Run as non-root with capability to bind low ports
user: "65532:65532"
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
restart: unless-stopped
labels:
- traefik.enable=true
# Shared middlewares for security and compression
- traefik.http.middlewares.secure-headers.headers.stsSeconds=31536000
- traefik.http.middlewares.secure-headers.headers.stsIncludeSubdomains=true
- traefik.http.middlewares.secure-headers.headers.stsPreload=true
- traefik.http.middlewares.secure-headers.headers.referrerPolicy=no-referrer
- traefik.http.middlewares.secure-headers.headers.browserXssFilter=true
- traefik.http.middlewares.secure-headers.headers.contentTypeNosniff=true
- traefik.http.middlewares.compress.compress=true
# Safer Docker socket access for Traefik (principle of least privilege)
docker-socket-proxy:
image: tecnativa/docker-socket-proxy:latest
environment:
- CONTAINERS=1
- SERVICES=1
- TASKS=1
- NETWORKS=1
- NODES=1
- INFO=1
- PING=1
- VERSION=1
- EVENTS=1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
expose:
- "2375"
networks:
- dockerproxy
read_only: true
security_opt:
- no-new-privileges:true
restart: unless-stopped
# Nextcloud application (Apache variant)
nextcloud:
image: nextcloud:29-apache # pin to a stable major/minor; update intentionally
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
environment:
- POSTGRES_HOST=db
- POSTGRES_DB=nextcloud
- POSTGRES_USER=nextcloud
- POSTGRES_PASSWORD_FILE=/run/secrets/nextcloud_db_password
- REDIS_HOST=redis
- NEXTCLOUD_TRUSTED_DOMAINS=${NEXTCLOUD_DOMAIN}
- TRUSTED_PROXIES=traefik
- OVERWRITEPROTOCOL=https
- PHP_MEMORY_LIMIT=1024M
- PHP_UPLOAD_LIMIT=2048M
volumes:
# granular persistence for clean upgrades
- nextcloud_data:/var/www/html/data
- nextcloud_config:/var/www/html/config
- nextcloud_custom_apps:/var/www/html/custom_apps
- nextcloud_themes:/var/www/html/themes
labels:
- traefik.enable=true
- traefik.http.routers.nextcloud.rule=Host(`${NEXTCLOUD_DOMAIN}`)
- traefik.http.routers.nextcloud.entrypoints=websecure
- traefik.http.routers.nextcloud.tls.certresolver=letsencrypt
- traefik.http.services.nextcloud.loadbalancer.server.port=80
- traefik.http.routers.nextcloud.middlewares=secure-headers@docker,nextcloud-buffering
# Allow large uploads and streaming
- traefik.http.middlewares.nextcloud-buffering.buffering.maxRequestBodyBytes=0
- traefik.http.middlewares.nextcloud-buffering.buffering.memRequestBodyBytes=8388608
- traefik.http.middlewares.nextcloud-buffering.buffering.maxResponseBodyBytes=0
networks:
- proxy
- nextcloud
secrets:
- nextcloud_db_password
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost/status.php || exit 1"]
interval: 30s
timeout: 10s
retries: 10
restart: unless-stopped
# Nextcloud cron (runs background jobs every 5 minutes)
nextcloud-cron:
image: nextcloud:29-apache
entrypoint: /cron.sh
depends_on:
- nextcloud
volumes:
- nextcloud_data:/var/www/html/data
- nextcloud_config:/var/www/html/config
- nextcloud_custom_apps:/var/www/html/custom_apps
- nextcloud_themes:/var/www/html/themes
networks:
- nextcloud
restart: unless-stopped
# PostgreSQL database for Nextcloud
db:
image: postgres:16-alpine
environment:
- POSTGRES_DB=nextcloud
- POSTGRES_USER=nextcloud
- POSTGRES_PASSWORD_FILE=/run/secrets/nextcloud_db_password
secrets:
- nextcloud_db_password
volumes:
- db_data:/var/lib/postgresql/data
networks:
- nextcloud
healthcheck:
test: ["CMD-SHELL", "pg_isready -U nextcloud -d nextcloud || exit 1"]
interval: 10s
timeout: 5s
retries: 10
restart: unless-stopped
# Redis for file locking and caching
redis:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis_data:/data
networks:
- nextcloud
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"]
interval: 10s
timeout: 5s
retries: 10
restart: unless-stopped
# Example simple website 1 (static content)
site1:
image: nginx:1.27-alpine
volumes:
- ./sites/site1:/usr/share/nginx/html:ro
labels:
- traefik.enable=true
- traefik.http.routers.site1.rule=Host(`${SITE1_DOMAIN}`)
- traefik.http.routers.site1.entrypoints=websecure
- traefik.http.routers.site1.tls.certresolver=letsencrypt
- traefik.http.services.site1.loadbalancer.server.port=80
- traefik.http.routers.site1.middlewares=secure-headers@docker,compress@docker
networks:
- proxy
read_only: true
tmpfs:
- /var/cache/nginx
- /var/run
restart: unless-stopped
# Example simple website 2 (static content)
site2:
image: nginx:1.27-alpine
volumes:
- ./sites/site2:/usr/share/nginx/html:ro
labels:
- traefik.enable=true
- traefik.http.routers.site2.rule=Host(`${SITE2_DOMAIN}`)
- traefik.http.routers.site2.entrypoints=websecure
- traefik.http.routers.site2.tls.certresolver=letsencrypt
- traefik.http.services.site2.loadbalancer.server.port=80
- traefik.http.routers.site2.middlewares=secure-headers@docker,compress@docker
networks:
- proxy
read_only: true
tmpfs:
- /var/cache/nginx
- /var/run
restart: unless-stopped
secrets:
nextcloud_db_password:
file: ./secrets/nextcloud_db_password.txt
volumes:
traefik_letsencrypt:
nextcloud_data:
nextcloud_config:
nextcloud_custom_apps:
nextcloud_themes:
db_data:
redis_data:
networks:
proxy:
driver: bridge
nextcloud:
driver: bridge
dockerproxy:
driver: bridge
Claude Sonet 4 (human senior engineer)
version: '3.8'
services:
# Database service
db:
image: mariadb:10.11
container_name: nextcloud_db
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=nextcloud_root_password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=nextcloud_password
- MARIADB_AUTO_UPGRADE=1
- MARIADB_DISABLE_UPGRADE_BACKUP=1
volumes:
- db_data:/var/lib/mysql
networks:
- nextcloud_network
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
start_period: 1m
start_interval: 10s
interval: 1m
timeout: 5s
retries: 3
# Redis cache service
redis:
image: redis:alpine3.22
container_name: nextcloud_redis
restart: unless-stopped
networks:
- nextcloud_network
command: redis-server --requirepass redis_password
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 30s
timeout: 3s
retries: 3
start_period: 30s
# Nextcloud application
nextcloud:
image: nextcloud:31.0.8-apache
container_name: nextcloud_app
restart: unless-stopped
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=nextcloud_password
- REDIS_HOST=redis
- REDIS_HOST_PASSWORD=redis_password
- NEXTCLOUD_ADMIN_USER=admin
- NEXTCLOUD_ADMIN_PASSWORD=admin_password
- TRUSTED_PROXIES=nginx-proxy-manager
- OVERWRITEPROTOCOL=https
- OVERWRITECLIURL=https://your-domain.com
- APACHE_DISABLE_REWRITE_IP=1
volumes:
- nextcloud_data:/var/www/html
- nextcloud_custom_apps:/var/www/html/custom_apps
- nextcloud_config:/var/www/html/config
- nextcloud_themes:/var/www/html/themes
networks:
- nextcloud_network
- proxy_network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/status.php"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# Nextcloud cron service
nextcloud_cron:
image: nextcloud:31.0.8-apache
container_name: nextcloud_cron
restart: unless-stopped
depends_on:
- nextcloud
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=nextcloud_password
- REDIS_HOST=redis
- REDIS_HOST_PASSWORD=redis_password
volumes:
- nextcloud_data:/var/www/html
- nextcloud_custom_apps:/var/www/html/custom_apps
- nextcloud_config:/var/www/html/config
- nextcloud_themes:/var/www/html/themes
networks:
- nextcloud_network
entrypoint: /cron.sh
user: www-data
# Nginx Proxy Manager
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:latest
container_name: nginx_proxy_manager
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "81:81"
environment:
- DB_SQLITE_FILE=/data/database.sqlite
volumes:
- npm_data:/data
- npm_letsencrypt:/etc/letsencrypt
networks:
- proxy_network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:81"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
volumes:
db_data:
driver: local
nextcloud_data:
driver: local
nextcloud_custom_apps:
driver: local
nextcloud_config:
driver: local
nextcloud_themes:
driver: local
npm_data:
driver: local
npm_letsencrypt:
driver: local
networks:
nextcloud_network:
driver: bridge
internal: true
proxy_network:
driver: bridge
GPT 4.1 output (human senior engineer)
version: "3.9"
services:
nextcloud:
image: nextcloud:31.0.8-apache
restart: unless-stopped
depends_on:
- db
- redis
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=nextcloud_db_password
- REDIS_HOST=redis
- REDIS_HOST_PASSWORD=redis_password
- NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.example.com
volumes:
- nextcloud_data:/var/www/html
networks:
- nextcloud_network
nextcloud-cron:
image: nextcloud:31.0.8-apache
restart: unless-stopped
entrypoint: "/cron.sh"
depends_on:
- db
- redis
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=nextcloud_db_password
- REDIS_HOST=redis
- REDIS_HOST_PASSWORD=redis_password
volumes:
- nextcloud_data:/var/www/html
networks:
- nextcloud_network
db:
image: mariadb:10.11
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=strong_root_password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=nextcloud_db_password
volumes:
- nextcloud_db:/var/lib/mysql
networks:
- nextcloud_network
redis:
image: redis:alpine3.22
restart: unless-stopped
command: ["redis-server", "--requirepass", "redis_password"]
volumes:
- nextcloud_redis:/data
networks:
- nextcloud_network
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:latest
restart: unless-stopped
ports:
- "80:80"
- "81:81"
- "443:443"
volumes:
- npm_data:/data
- npm_letsencrypt:/etc/letsencrypt
networks:
- nextcloud_network
volumes:
nextcloud_data:
nextcloud_db:
nextcloud_redis:
npm_data:
npm_letsencrypt:
networks:
nextcloud_network:
driver: bridge
GPT 5 output (human senior engineer)
name: nextcloud-stack
services:
db:
image: mariadb:10.11
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-file-per-table=1 --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
restart: unless-stopped
environment:
- MARIADB_DATABASE=nextcloud
- MARIADB_USER=nextcloud
- MARIADB_ROOT_PASSWORD_FILE=/run/secrets/db_root_password
- MARIADB_PASSWORD_FILE=/run/secrets/db_password
volumes:
- db_data:/var/lib/mysql
secrets:
- db_root_password
- db_password
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u root -p$(cat /run/secrets/db_root_password) || exit 1"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
redis:
image: redis:alpine3.22
restart: unless-stopped
command: ["redis-server", "--save", "", "--appendonly", "no"]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
networks:
- backend
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
app:
image: nextcloud:31.0.8-apache
restart: unless-stopped
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD_FILE=/run/secrets/db_password
- REDIS_HOST=redis
- OVERWRITEPROTOCOL=https
- APACHE_DISABLE_REWRITE_IP=1
volumes:
- nextcloud:/var/www/html
secrets:
- db_password
networks:
- backend
- frontend
healthcheck:
test: ["CMD-SHELL", "php -r \"exit((int)!@fopen('http://127.0.0.1/status.php', 'r'));\""]
interval: 30s
timeout: 10s
retries: 10
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
cron:
image: nextcloud:31.0.8-apache
restart: unless-stopped
depends_on:
app:
condition: service_started
entrypoint: /cron.sh
volumes:
- nextcloud:/var/www/html
networks:
- backend
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
npm:
image: jc21/nginx-proxy-manager:latest
restart: unless-stopped
ports:
- "80:80"
- "81:81"
- "443:443"
volumes:
- npm_data:/data
- npm_letsencrypt:/etc/letsencrypt
networks:
- frontend
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
nextcloud:
db_data:
npm_data:
npm_letsencrypt:
secrets:
db_root_password:
file: ./secrets/db_root_password.txt
db_password:
file: ./secrets/db_password.txt
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true

Comments
Post a Comment