Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

n3pix's avatar
Level 1

I want to deploy my Laravel Sail application with other Next.js and Socket.io servers

I have been building a project with Laravel Sail for standalone REST API with MySQL + Redis. For the front-end I have a Next.js application and to handle real-time needs I have a separate Node.js + Socket.io server. These 3 were always isolated code bases and I had to launch them separately when I was developing.

Now that I want to deploy my application to the internet, I want to configure my code base and ship it to my VPS and serve from there.

Why VPS? My project is cosiderably a small project and for cost-wise efficiency I chose VPS over other cloud services.

I don't have much experience with Docker but I know a bit about it. I wonder if I should make these 3 code-bases into one mono-repo and have a single docker-compose.yml file on the root of the code base? Or should I still manage each of these repos/services separately? How should I approach?

1 like
14 replies
vincent15000's avatar

I think that it's over all a choice you have to do.

If you want that all services are isolated, you can work with microservices and enclose each one in a docker environment.

I would put inside docker all the minimum necessary for the application to work.

And what is not necessary to guarantee a minimum operation, you can eventually put it in another docker environment.

I also don't know so much about docker, but I have worked with docker for 6 months with an expert.

1 like
n3pix's avatar
Level 1

@vincent15000 I gave a shot on preparing a common docker-compose.yml file to set-up and spin up all the services together with assist of ChatGPT. I had a file structore like below:

- monorepo/
  - docker-compose.yml
  - .env (Environment variables required for docker-compose.yml)
  - backend/ (Laravel Sail)
    - docker/
      - 8.3/
        -Dockerfile
  - frontend/ (Next.js)
    - Dockerfile
  - socketio (Node.js + Socket.io Server)
    - Dockerfile
  - nginx/
    - nginx.conf

And below is was my resulting docker-compose.yml file:

It basically has an NGINX to reverse proxy the requests to respective services that run on port 8000 (backend), 3000 (frontend), 4000 (socket.io). It also had some SLL config but I removed them due to some errors. This docker-compose.yml file kind of extends what we have in Laravel Sail proejcts.

n3pix's avatar
Level 1

@vincent15000 I had some issues with this docker-compose.yml file.

  1. I normally used the ./vendor/bin/sail up -d command to spin up my Laravel Sail project in dev environment. I dug in and see that it defines some environment variables such as WWWUSER, WWWGROUP, PWD etc. for spinning up the Laravel and it's related services. So I had to manually set these environment variables similary in my root docker-composer.yml, otherwise when I run docker compose up -d it would warn me that some of these used env variables were not set and the process would eventually fail.
  2. Seems like Laravel Sail project already has a NGINX config and service somewhere. Defining my own NGINGX might not be good as it duplicates and such.
  3. For some reason when I opened the file system of backend service, I have seen that I had 3 folders in var/www/html folder. These 3 folders were backend, frontend and socketio. I would normally assume that I have only the backend related files in backend service's file system. I don't know why this happend.
  4. Socket.io service was failing to connect to the Redis with URL redis://localhost:6379/0. Don't know why this happens as they are all on the same network confired in docker-compose.yml file.
1 like
vincent15000's avatar

@n3pix You shouldn't use Sail in production, it's only for development envrionment.

I suggest you to use 3 different docker-compose files :

  • docker-compose.yml for all configuration that is identical between dev and prod

  • docker-compose.override.yml with specific dev configuration, it's automatically loaded with sail

  • docker-compose.prod.yml with specific production configuration, you'll need to call it when you execute docker

1 like
n3pix's avatar
Level 1

@vincent15000 thanks for sharing your opinion. I have solved this issues I have mentioned. As you mentioned, I have a similar docker-compose file structure. I have a docker-compose.yml for common configuration, docker-compose.dev.yml for development env and docker-compose.prod.yml for production env.

May I know why Sail shouldn't be used in production? I currently use it for production.

1 like
vincent15000's avatar

@n3pix Among the reasons, sail doesn't use any webserver, just the built in PHP dev server.

If you have solved your problem, please assign a best answer to close the post.

1 like
n3pix's avatar
n3pix
OP
Best Answer
Level 1

@vincent15000

So as I mentioned from my indecision between having 3 separate repos or single mono-repo to manage Laravel Sail backend, Next.js frontend and Socket.io server, I chose to go with mono-repo approach as it seemed easier for me to handle and as my project is not something large or something that's gonna be serving like tens of thousands of users. If I were to serve a large number of users, separate repos seems like a better approach because at some point you can instantiate more copies of each service (backend, frontend or socket.io etc.) as you need using orchestration tools like Kubernetes.

With mono-repo approach I have gathered all 3 of my once-was separate repos into one large repo and the folder structure is as below:

mono-repo/
├── backend
│   └── docker/
│       └── 8.3/
│           └── Dockerfile
├── frontend/
│   ├── Dockerfile
│   └── Dockerfile.dev
├── socketio
│   ├── Dockerfile
│   └── Dockerfile.dev
├── nginx/
│   ├── nginx.conf
│   └── certificates/
│       ├── domain.key.pem
│       └── private.key.pem
├── .env.example
├── .env
├── .env.development (If development)
├── .env.production (If production)
├── docker-compose.yml
├── docker-compose.dev.yml
├── docker-compose.prod.yml
└── sync-env.sh

So as you can see backend, frontend and socketio folders under the root mono-repo folder are each once-was separate repos. Each of these services has their separate Dockerfile and Dockerfile.dev to instruct how to prepare and launch them.

Dockerfile is used for production and it usually builds the services such as frontend and socketio code. Dockerfile.dev is used for development and it doesn't build projects, just launches them and allows modifications to project files, watches the source code for changes and hot-reloads services.

On the root folder there is .env.example file which I copy to create .env and depending on the environment .env.development or .env.production files. (You might be wondering why there is .env file if there is already .env.development or .env.production files. And the answer is I don't know either lol). I also have another bash file named sync-env.sh which fills the .env files used in each service, reducing need to define separate .env.development or .env.production file in each service. This way I manage environment variables from one place and whenever I need to update .env of any of the service, I just run sudo bash sync-env.sh and ta-da!

And finally, the whole thing come together in docker-compose.yml, docker-compose.dev.yml and docker-compose.prod.yml files under the root folder. docker-compose.yml defines general and common structure of other two environment dependent docker files. I just override some parts of the docker-compose.yml in the other two files for the specific environment to reduce the need of creating docker-compose.override.yml file. I will share content of these files in the following comment:

1 like
n3pix's avatar

docker-compose.yml:

This file is just an extended version of docker-compose.yml file you will find in your regular Laravel Sail application's root folder. backend, mysql, redis service definitions are mostly generated from Laravel Sail along with the networks and volumes parts. I have additionally defined services for my frontend and socketio services. And I added an nginx service to reverse-proxy requests made to 80 or 443 ports of my localhost to each service running on ports 3000 (frontend), 4000 (socketio), 8000 (backend). I will share my nginx.conf shortly.

The docker-compose.dev.yml file looks the same as docker-compose.yml except definitions for frontend and socketio services point to respective service folder's Dockerfile.dev file to prevent projects from being built when developing.

The docker-compose.prod.yml does also look similiar to docker-compose.yml file. The only difference is that I removed XDEBUG_MODE, XDEBUG_CONFIG, IGNITION_LOCAL_SITES_PATH enviroment variable definitions in backend service since we don't need any debugging in production. Another thing is I removed all ports definitions in all services except the nginx service to prevent requests made to 3000, 4000, 8000 , 3306, 6379 ports. Users can only reach to my domain and not domain:3000 or other ports as a minor security measurement. (Note: I used expose instead of ports to definition for that purpose in each service.)

And for the last step, nginx.conf:

This nginx.conf simply reverse-proxies the requests made to server_name golden-dirt.dev address to each defined service as instructed. It also adds SSL certificates that I acquired by my domain provider but you can create self-signed SSL certificates using certbot for both development and production. And lastly, there is a simple request throttling definition at beginnig of the file: limit_req_zone \$binary_remote_addr zone=mylimit:20m rate=20r/s; when users make too many requests in defined parameters, they receive 503 service unavaialble response to prevent DDoS attacks. (Don't know how effective this is but it seems to be doing a great job, though I had to increase parameters since some of the requests that my website do to acquire static assets like images and so on was blocked by this measurement, so I had to increase the limits a bit.)

1 like

Please or to participate in this conversation.