JhumanJ / OpnForm

Beautiful Open-Source Form Builder
https://opnform.com
GNU Affero General Public License v3.0
2.22k stars 297 forks source link

Enhance Docker Setup #445

Closed JhumanJ closed 2 months ago

JhumanJ commented 5 months ago

Enhance Docker Setup

Description:

We need to create Docker images for the Laravel backend (PHP service only) and the Nuxt.js frontend. Additionally, we need to set up Docker Compose configurations to orchestrate these services along with necessary supporting services like the database, Redis, Minio, and Nginx. The setup should be easy to use and suitable for both production and local development environments. Finally, update the GitHub CI workflow to publish the Docker images.

Tasks:

  1. Create Docker Images:

    • Laravel Backend: Create a Dockerfile for the Laravel application (PHP service only).
    • Nuxt.js Frontend: Create a Dockerfile for the Nuxt.js application.
  2. Docker Compose Setup:

    • Create a docker-compose.yml file for production that combines the Laravel backend, Nuxt.js frontend, Nginx, and additional services (Postgres, Redis, Minio).
    • Create a docker-compose.dev.yml file for local development with the same services, but configured for a development environment (e.g., enabling hot reloading for Nuxt.js).
  3. Update GitHub CI Workflow:

    • Update the GitHub Actions workflow to build and publish the Docker images for the Laravel and Nuxt.js applications.

Requirements:

  1. Dockerfile for Laravel Backend:

    • Build a Docker image for the Laravel application, excluding Nginx (to be handled in Docker Compose).
    • Use Docker environment variables for configuration.
  2. Dockerfile for Nuxt.js Frontend:

    • Build a Docker image for the Nuxt.js application.
    • Use Docker environment variables for configuration.
  3. Docker Compose Configuration:

    • Production: Define a docker-compose.yml file for production that includes services for Laravel, Nuxt.js, Nginx, Postgres, Redis, and Minio. Ensure services are properly networked and can communicate with each other.
    • Development: Define a docker-compose.dev.yml file for local development. Configure the Nuxt.js service to support hot reloading and ensure that the setup is optimized for a development environment.
    • Use Docker environment variables to configure each service.
  4. GitHub CI Workflow:

    • Modify the existing CI workflow to build Docker images for both the Laravel backend and Nuxt.js frontend.
    • Ensure the workflow publishes the Docker images to the appropriate Docker registry.

Additional Notes:

JhumanJ commented 5 months ago

/bounty $150

algora-pbc[bot] commented 5 months ago

πŸ’Ž $150 bounty β€’ OpnForm

Steps to solve:

  1. Start working: Comment /attempt #445 with your implementation plan
  2. Submit work: Create a pull request including /claim #445 in the PR body to claim the bounty
  3. Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts

Thank you for contributing to JhumanJ/OpnForm!

Add a bounty β€’ Share on socials

Attempt Started (GMT+0) Solution
πŸ”΄ @ezhil56x Jun 10, 2024, 11:42:46 AM WIP
πŸ”΄ @rajeshj11 Jun 10, 2024, 2:56:05 PM WIP
πŸ”΄ @LL-Etiane Jun 25, 2024, 5:31:47 AM WIP
πŸ”΄ @varshith257 Jul 6, 2024, 8:38:05 AM WIP
ezhil56x commented 5 months ago

/attempt #445 @JhumanJ I would like to work on this. Is assignment required?

Algora profile Completed bounties Tech Active attempts Options
@ezhil56x 33 bounties from 11 projects
JavaScript, TypeScript,
Rust & more
Cancel attempt
JhumanJ commented 5 months ago

@ezhil56x, sure please go ahead!

ben-pr-p commented 5 months ago

In general, I'd suggest fully completing portion 2 of this (Application Separation) as a smaller task before tackling anything else here.

For most users who will self host, 2 will be enough to unlock everything, since they will have an existing approach to SSL provisioning and database management, and object storage.

Additionally, using Docker for development is not at all a requirement for using it in production. Developing a Docker for development serves a totally different audience (contributors) than Dockerizing for production (people who want to self host).

I also would not create documentation for provisioning an SSL certificate that's separate from any specific setup. Docker-compose + Let's Encrypt may be right for a user who just has a box, but it's not right for someone on Kubernetes or taking the container to a container-serving platform like Render or Fly, which would be great platforms to self-host OpnForm with.

I would leave that off of any initial documentation, and then add specific "Deploy with Fly", "Deploy with Render", "Deploy on a VPS", "Deploy on Kubernetes" sections to docs down the line once the core image is tested.

Backend Laravel Application: Setup a Docker service for the backend Laravel application with Nginx.

Unless I'm missing something and the relationship between Laravel and Nginx is different that other web servers and Ngninx, you do not want Nginx to be inside of the same container as your application server.

Nginx can either be in a separate container, managed as part of a cloud load balancer, or not used at all.

Determine the best way to handle two environment files (.env for Laravel and .env for Nuxt).

You don't want to make the user mount .env files inside the containers. You want to use real environment variables inside the containers, since that's the post integratable with other things like Kubernetes secrets, etc. I don't see any reason this application needs a persistent volume at all - if that's just for the .env files, I think that dependency can be removed.

JhumanJ commented 5 months ago

Thanks for the detailed feedback @ben-pr-p. Some notes:

  • I added step 1. so that users can be able to easily "disable" some services from the docker compose setup to easily replace them with their own
  • Removed the mention to SSL to keep things simple
  • Laravel is just a PHP framework so we do need a web server (nginx in our case). It seems to to me that's this is the recommended way, example here.
  • Simplified the mention to .env files

@ezhil56x please don't start working on this while we work on requirements, thanks!

ezhil56x commented 5 months ago

@JhumanJ It would be great if you can ping me when the requirements are ready. Looking forward to contribute to this amazing project!

ben-pr-p commented 5 months ago

@JhumanJ

Laravel is just a PHP framework so we do need a web server (nginx in our case). It seems to to me that's this is the recommended way, example here.

In this example, the PHP server and the Ngninx server are (correctly) in 2 separate containers: https://github.com/refactorian/laravel-docker/blob/main/docker-compose.yml#L6-L25

. so that users can be able to easily "disable" some services from the docker compose setup to easily replace them with their own

What's useful is the published image of Opnform - the Docker compose bits are only useful at all for a limited range of self-hosting options. If you're hosting on Fly, Render, or Kubernetes, you don't use the Docker compose bits at all, you just use the 2 OpnForm images.

Unless you have a specific self-hosting setup in mind that requires Docker compose, I would not involve it in this issue at all.

JhumanJ commented 5 months ago

@ben-pr-p what do you think of the following?


GitHub Issue: Create Docker Images and Docker Compose Setup for OpnForm

Title:

Create Docker Images for Laravel and Nuxt.js and Integrate with Docker Compose for Production and Development

Description:

We need to create Docker images for the Laravel backend (PHP service only) and the Nuxt.js frontend. Additionally, we need to set up Docker Compose configurations to orchestrate these services along with necessary supporting services like the database, Redis, Minio, and Nginx. The setup should be easy to use and suitable for both production and local development environments. Finally, update the GitHub CI workflow to publish the Docker images.

Tasks:

  1. Create Docker Images:

    • Laravel Backend: Create a Dockerfile for the Laravel application (PHP service only).
    • Nuxt.js Frontend: Create a Dockerfile for the Nuxt.js application.
  2. Docker Compose Setup:

    • Create a docker-compose.yml file for production that combines the Laravel backend, Nuxt.js frontend, Nginx, and additional services (Postgres, Redis, Minio).
    • Create a docker-compose.dev.yml file for local development with the same services, but configured for a development environment (e.g., enabling hot reloading for Nuxt.js).
  3. Update GitHub CI Workflow:

    • Update the GitHub Actions workflow to build and publish the Docker images for the Laravel and Nuxt.js applications.

Requirements:

  1. Dockerfile for Laravel Backend:

    • Build a Docker image for the Laravel application, excluding Nginx (to be handled in Docker Compose).
    • Use Docker environment variables for configuration.
  2. Dockerfile for Nuxt.js Frontend:

    • Build a Docker image for the Nuxt.js application.
    • Use Docker environment variables for configuration.
  3. Docker Compose Configuration:

    • Production: Define a docker-compose.yml file for production that includes services for Laravel, Nuxt.js, Nginx, Postgres, Redis, and Minio. Ensure services are properly networked and can communicate with each other.
    • Development: Define a docker-compose.dev.yml file for local development. Configure the Nuxt.js service to support hot reloading and ensure that the setup is optimized for a development environment.
    • Use Docker environment variables to configure each service.
  4. GitHub CI Workflow:

    • Modify the existing CI workflow to build Docker images for both the Laravel backend and Nuxt.js frontend.
    • Ensure the workflow publishes the Docker images to the appropriate Docker registry.

Additional Notes:

  • The setup should be easy to use, even for those not familiar with Docker.
  • Provide clear and concise documentation for setting up and using the Docker Compose configurations for both production and development.
  • Test the setup to ensure it works seamlessly for both development and production environments.
  • Please also update the readme with explanations on how to run the project (both for production and local development)
ben-pr-p commented 5 months ago

Looks good!

JhumanJ commented 5 months ago

Thanks @ben-pr-p πŸ™

The task is now ready to be started @ezhil56x. Are you familiar enough with docker etc though? I remember you had some issues with the existing setup. Thanks!

ezhil56x commented 5 months ago

Thanks @ben-pr-p πŸ™

The task is now ready to be started @ezhil56x. Are you familiar enough with docker etc though? I remember you had some issues with the existing setup. Thanks!

I have been self hosting for a while and dockerized a couple of medium scale projects. It would be better if it's assigned! Thanks!

JhumanJ commented 5 months ago

Great. Not sure to understand what you mean "It would be better if it's assigned!"

ezhil56x commented 5 months ago

Sorry for the confusion. Do I need to get the issue assigned before starting?

JhumanJ commented 5 months ago

Oh - assigned to you.

ezhil56x commented 5 months ago

Thanks!

rajesh-jonnalagadda commented 5 months ago

/attempt #445 @JhumanJ I would also like to give it a try

Algora profile Completed bounties Tech Active attempts Options
@rajeshj11 4 bounties from 3 projects
JavaScript, TypeScript,
HTML
Cancel attempt
algora-pbc[bot] commented 5 months ago

[!NOTE] The user @ezhil56x is already attempting to complete issue #445 and claim the bounty. We recommend checking in on @ezhil56x's progress, and potentially collaborating, before starting a new solution.

rajesh-jonnalagadda commented 5 months ago

hey @ezhil56x , I would like to collaborate with you. if need any help/assistance on this task.

ezhil56x commented 5 months ago

@rajeshj11 Will let you know, if I need any help!

ezhil56x commented 5 months ago

@JhumanJ I am confused which one to use for laravel backend image. Which one do you prefer for starting the laravel backend php artisan serve or nginx + php-fm ?

JhumanJ commented 5 months ago

@JhumanJ

I am confused which one to use for laravel backend image.

Which one do you prefer for starting the laravel backend php artisan serve or nginx + php-fm ?

Artisan serve is for local development, please use Nginx and php fpm

ezhil56x commented 5 months ago

Just to confirm, the laravel backend image should use php artisan serve for development and use nginx + php fpm for production. Is that right?

JhumanJ commented 5 months ago

Please not that Nginx should be handled separately in the Docker Compose setup, not included directly in the backend image

ezhil56x commented 5 months ago

Please not that Nginx should be handled separately in the Docker Compose setup, not included directly in the backend image

We can't use php fpm without including nginx in the laravel backend image.

ezhil56x commented 5 months ago

@ben-pr-p @JhumanJ So the idle way would be to include nginx and expose it using http. So that self hosting people can setup reverse proxy for SSL. By this way the image can be used to create a container without compose. If the image has only php service we can't run image, either we need to use nginx + php fpm or we can use php artisan serve in the image

Correct if I'm wrong

JhumanJ commented 5 months ago

I believe PHP-FPM can and should run independently of Nginx. PHP-FPM is a process manager for PHP that listens for requests, typically from a web server like Nginx, and executes PHP scripts

ezhil56x commented 5 months ago

I believe PHP-FPM can and should run independently of Nginx. PHP-FPM is a process manager for PHP that listens for requests, typically from a web server like Nginx, and executes PHP scripts

If so I don't think the backend image with only the php service can be run independently in vps and kubernetes ie, without using compose. In this case adding NGINX to the image would be a better option. What do you think to this?

What start command should I use if its only php service

ezhil56x commented 5 months ago

@ben-pr-p Can you please share your thoughts on this

ben-pr-p commented 5 months ago

@ezhil56x php-fpm is the way to go.

On a VPS, you'll run Docker Compose, in which case the NGINX that exists in a separate container is available.

On Kubernetes, the docker image will be part of a deployment, which is routed to by a service, which is then finally routed to from a load balancer, which is usually NGINX itself. If the container is deployed as part of Render/Fly/Google Cloud Run, their infrastructure will handle the layer that NGINX serves on a VPS.

In other words, it's not the role of the container to be able to run with no other layer on a VPS/Kubernetes.

In both cases, Nginx should not be in the container, and will be run separately as part of the setup.

ezhil56x commented 4 months ago

@JhumanJ @ben-pr-p Found that php-fpm cannot handle http requests without nginx. So I think we need to use nginx in the image. The nginx I'm referring is not about the vps provider nginx. This is a separate nginx that need to be added with the image to handle http request. The container created with the image will expose 80 to handle http request and then we can map with any custom port like 8000:80

Found this https://youtu.be/lh4RnczaATI?si=YDNIVonA6Sla0xZa

image

flece commented 4 months ago

Hi,

when it comes to Docker you want to have 2 different Things. 1) Your Image what you upload to an registry for other ppl (or youself) to run 2) Your Setup for Running this Image (imho easiest way for this is an "docker-compose.yaml")

For 1) you need an Baseimage and than put only your app and necessary things in it.

We are all on the same Page with Redis, Database and SSL-Termination (userfacing webserver) belong to 2) and not to 1) What but how to tackle PHP?

This is not as trivial as one might thing. but i found an excellent post about that topic here: https://medium.com/@emmanuelmerali/a-lean-base-docker-image-for-php-63ded6c13733

by the way. it is totally ok to have "nginx-proxy (SSL-termination)" in front of "nginx-running-php" in the back

ezhil56x commented 4 months ago

@flece What I meant is to create a backend image with php8.3-fpm and nginx as base images. Is this what you are suggesting too?

flece commented 4 months ago

@ezhil56x No! ONLY if you have good reason. for example you need to modifiy the Configuration for nginx

Otherwise your image should only provide php-fpm on port "9000" (you can also connect them via socket on the internal Dockernetwork) an example docker-conmpose.yaml can be found here: https://github.com/joseluisq/alpine-php-fpm/blob/master/examples/nginx/docker-compose.yml or here https://stackoverflow.com/questions/47056062/how-to-connect-nginx-to-php-fpm-using-unix-socket-in-docker

but far more important is to choose the right baseimage to start from: i would go with "php:8.3-fpm-alpine" because it is so much smaller baseimages can be found here: https://hub.docker.com/_/php/tags?page=&page_size=&ordering=&name=alpine

  • 8.3-fpm-alpine = 31.23 MB
  • 8.3-fpm = 166.25 MB

and for reference:

  • nginx:stable-alpine = 19.5 MB
ezhil56x commented 4 months ago

If we are using compose then exposing over 9000 is good to go as we will be having another nginx service in the compose which handles http requests. But in kubernetes we can only deploy using the image so that if it's exposed in port 9000 it can't handle http requests without a dedicated web server like nginx. Hope so you got it

algora-pbc[bot] commented 4 months ago

@ezhil56x: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then πŸ™

algora-pbc[bot] commented 4 months ago

@rajeshj11: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then πŸ™

JhumanJ commented 4 months ago

Hey @ezhil56x,

Great points on the Docker config!

We’re aiming to keep our Docker images lean, so let’s set up the Laravel backend with just PHP-FPM and handle Nginx separately in the Docker Compose or Kubernetes setup. This keeps our setup flexible and scalable.

I don't really want to focus on Kubernetes for now, but typically an ingress controller should be used to manage HTTP traffic, sticking to the microservices principle of each service doing one thing well.

For now, let's focus on the docker composer direction. Please go ahead with the PHP-FPM container setup as we discussed. We can always tweak things later based on how they perform in real scenarios.

ezhil56x commented 4 months ago

@JhumanJ Sorry, I couldn't make it, cancelling my attempt. Made some progress though, attaching it for future reference. https://gist.github.com/ezhil56x/566ff5438f1e7449a8343854395f4a84

JhumanJ commented 4 months ago

Thanks for sharing your progress @ezhil56x πŸ™ @rajeshj11 would you still be interested in giving this a try?

ben-pr-p commented 4 months ago

@ezhil56x what is left to do / not working from what you shared?

ezhil56x commented 4 months ago

@ezhil56x what is left to do / not working from what you shared?

Nginx config and env variables were not working as expected.

algora-pbc[bot] commented 4 months ago

The bounty is up for grabs! Everyone is welcome to /attempt #445 πŸ™Œ

LL-Etiane commented 4 months ago

/attempt #445 Will love to give it a try

JhumanJ commented 4 months ago

Hey @LL-Etiane are you working on this? Or should I clear this task?

LL-Etiane commented 4 months ago

@JhumanJ Yes. Did something but had some errors on it. Should be done soon

algora-pbc[bot] commented 4 months ago

@LL-Etiane: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then πŸ™

LL-Etiane commented 4 months ago

@JhumanJ haven't succeed to get it up and running, you can clear it

JhumanJ commented 4 months ago

Ok thanks for trying. Can you please cancel your attempt? @LL-Etiane

LL-Etiane commented 4 months ago

yes sure.