hosting a react web app and a docker laravel app with nginx - laravel

I have 2 apps I'm trying to host on one machine (Ubuntu 22). The first app is a client side react app that makes api calls to my backend which is a docker compose laravel/nginx/sql. I went into sudo vim /etc/nginx/sites-available/MY.DOMAIN.COM and added the following:
server {
listen 80;
root /var/www/html;
index index.php index.html index.htm; #index.nginx-debian.html;
server_name MY.IP.ADDRESS.HERE;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 81;
listen [::]:81;
root /var/www/html/public;
index index.php index.html index.htm index.nginx-debian.html;
server_name MY_DOMAIN_NAME.COM www.MY_DOMAIN_NAME.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
On port 80 is where my react app lives. When someone visits MY.DOMAIN.COM I'm able to serve it without any issues. I'm not sure why putting server_name MY.IP.ADDRESS.HERE; works there vs the domain name like I did for port 81 server_name MY_DOMAIN_NAME.COM www.MY_DOMAIN_NAME.com;. Anyway on port 81 is where my laravel app should live. It's using a docker-compose.yml with this configuration:
version: "3.7"
services:
app:
build:
args:
user: admin
uid: 1000
context: ./
dockerfile: Dockerfile
image: my-laravel
container_name: my-laravel-app
restart: unless-stopped
working_dir: /var/www/
# command: bash -c "php artisan migrate:fresh --seed"
# depends_on:
# - db
# links:
# - db
volumes:
- ./:/var/www
networks:
- my-laravel
db:
image: mysql:8.0.30
container_name: my-laravel-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- ./docker-compose/mysql:/docker-entrypoint-initdb.d
networks:
- my-laravel
nginx:
image: nginx:alpine
container_name: my-laravel-nginx
restart: unless-stopped
ports:
- '8081:81'
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d/
networks:
- my-laravel
networks:
my-laravel:
driver: bridge
The react app is trying to make api calls to const domain = "http://MY.IP.ADDRESS.HERE:8081"; and fails with the message net::ERR_CONNECTION_REFUSED This is where I'm not sure what I did wrong.
I have nginx installed, but I'm also using it in the docker image. Is there any conflict there? Do I even need to configure my installed nginx instance to serve the docker image?
Anyway, the funny thing is I had this all setup and working last week, but I decided to add an ssl cert with cert bot which messed everything up and now I'm starting from scratch. The problem is I don't remember how I got it working to being with lol.
Any help here would be greatly appreciated, thank you in advance.

Related

Deploying Laravel backend and multiple vue frontend apps on the same server

I have a Laravel and several Vue apps. I'm trying to deploy them on Digital Ocean using docker and nginx.
I've never deployed apps before, so I poorly understand the process. I've already deployed Laravel backend and I am thinking of deploying my vue apps in separate docker containers, but I dont actually understand how should I configure my nginx server.
I've found out I could build my frontend app into the Laravel's public folder, but this approach works with a single Vue app, while I have several.
I'd use some help on how to manage this. Thanks in advance!
Here's my docker-compose.yml(without vue yet) :
version: '3'
services:
nginx:
image: nginx:alpine
container_name: shop_nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www/shop/backend
- ./nginx/conf.d/:/etc/nginx/conf.d/
- ./nginx/ssl/:/etc/nginx/ssl/
networks:
- shop
laravel:
container_name: shop_laravel
restart: unless-stopped
build:
context: .
dockerfile: Dockerfile
volumes:
- '.:/var/www/shop/backend'
networks:
- shop
depends_on:
- pgsql
- redis
pgsql:
container_name: shop_postgres
restart: unless-stopped
image: 'postgres:14'
ports:
- '5432:5432'
environment:
PGPASSWORD: 'shop'
POSTGRES_DB: 'shop'
POSTGRES_USER: 'shop'
POSTGRES_PASSWORD: 'shop'
volumes:
- 'shop-pgsql:/var/lib/postgresql/data'
networks:
- shop
redis:
container_name: shop_redis
restart: unless-stopped
image: 'redis:alpine'
ports:
- '6379:6379'
volumes:
- 'shop-redis:/data'
networks:
- shop
networks:
shop:
driver: bridge
volumes:
shop-pgsql:
driver: local
shop-redis:
driver: local
And nginx configuration:
server {
listen 80;
listen [::]:80;
server_name shop.laravel;
root /var/www/shop/backend/public;
index index.php;
charset utf-8;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass laravel:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}

Laravel Sail (docker), nginx reverse proxy - Html renders localhost:8002 instead of site.xyz

I started testing the new Laravel Sail docker-compose environment with an nginx reverse proxy so I can access my website from a real tld while developing on my local machine.
My setup is:
OS - Ubuntu Desktop 20 with nginx and docker installed.
Nginx site-enabled on the host machine:
server {
server_name mysite.xyz;
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/ssl/certs/mysite.xyz.crt;
ssl_certificate_key /etc/ssl/private/mysite.xyz.key;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
location / {
proxy_pass http://localhost:8002;
}
}
Also I have 127.0.0.1 mysite.xyz in my host machine /etc/hosts file
And my docker-compose:
# For more information: https://laravel.com/docs/sail
version: '3'
services:
laravel.test:
build:
context: ./vendor/laravel/sail/runtimes/8.0
dockerfile: Dockerfile
args:
WWWGROUP: '${WWWGROUP}'
image: sail-8.0/app
ports:
- '8002:80'
environment:
WWWUSER: '${WWWUSER}'
LARAVEL_SAIL: 1
volumes:
- '.:/var/www/html'
networks:
- sail
depends_on:
- mysql
- redis
image: 'mysql:8.0'
ports:
- '${FORWARD_DB_PORT:-3306}:3306'
environment:
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
MYSQL_DATABASE: '${DB_DATABASE}'
MYSQL_USER: '${DB_USERNAME}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
volumes:
- 'sailmysql:/var/lib/mysql'
networks:
- sail
redis:
image: 'redis:alpine'
ports:
- '${FORWARD_REDIS_PORT:-6379}:6379'
volumes:
- 'sailredis:/data'
networks:
- sail
networks:
sail:
driver: bridge
volumes:
sailmysql:
driver: local
sailredis:
driver: local
Site is loading fine when I access mysite.xyz from my host machine.
The issue I'm having is that on the register page that I ca see from my host machine by accessing the register page (https://mysite.xyz/register) the form action is: http://localhost:8002/register
The piece of code that generates the above url is <form method="POST" action="{{ route('register') }}">
This is a problem because I don't access the site from localhost:XXXX but instead from mysite.xyz which goes through the nginx reverse proxy and eventually ends up pointing to http://localhost:8002/register
**
What I checked:
In my Laravel .env file, the APP_URL is mysite.xyz
if I ssh into the the sail container and start artisan tinker and then run route('register') it outputs https://mysite.xyz/ so clearly, the laravel app inside the container seems to be behaving correctly.
The funny thing is that when it renders the html response, it renders the register route as http://localhost:8002/register
I tried searching the entire project for localhost:8002 and I can find it in /storage/framework/sessions/asdofhsdfasf8as7dgf8as7ogdf8asgd7
that bit of text says: {s:3:"url";s:27:"http://localhost:8002/login";}
So it seems that the session thinks it's localhost:8002 but tinker thinks it's mysite.xyz
I'm also a docker noob so who knows what I'm missing. I'm lost :)
The "problem" lies within your nginx configuration, not your code:
proxy_pass http://localhost:8002;
Laravel uses APP_URL in CLI (console) or whenever you use config('app.url') or env('APP_URL') in your code. For all other operations (such as URL constructing via the route helper) Laravel fetches the URL from the request:
URL Generation, Laravel 8.x Docs
The url helper may be used to generate arbitrary URLs for your application. The generated URL will automatically use the scheme (HTTP or HTTPS) and host from the current request being handled by the application.
What you need to do is to pass the correct URL and port in your nginx configuration, by adding:
proxy_pass http://localhost:8002;
proxy_set_header Host $host;
For additional information on the topic, you may want to have a look at this article: Setting up an Nginx Reverse Proxy

How to use Laravel docker container & MySQL DB with a Vue one?

I have an app which uses Vue CLI as a front-end and Laravel as a back-end. Now I am trying to launch my app on a server using docker.
My docker skills can only allow me one thing: Vue docker container. But as far as I have to use Laravel as a back-end I have to create a container for that too (+ MySQL, of course).
So here what I've got: Dockerfile
FROM node:lts-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
EXPOSE 8080
CMD ["npm", "run", "serve"]
docker-compose.yml
version: '3'
services:
web:
build: .
stdin_open: true
tty: true
ports:
- "8080:8080"
volumes:
- "/app/node_modules"
- ".:/app"
The problem is that I understand how to connect Laravel into Dockerfile. It just doesn't add up in my mind.
May be I should use Ubuntu, not just node? Anyways, I'm asking once again for your support
According to this article you will need to follow the steps below.
Make your project folder look like this: (d: directory, f: file)
d: backend
d: frontend
d: etc
d: nginx
d: conf.d
f: default.conf.nginx
d: php
f: .gitignore
d: dockerize
d: backend
f: Dockerfile
f: docker-compose.yml
Add docker-compose.yml
version: '3'
services:
www:
image: nginx:alpine
volumes:
- ./etc/nginx/conf.d/default.conf.nginx:/etc/nginx/conf.d/default.conf
ports:
- 81:80
depends_on:
- backend
- frontend
frontend:
image: node:current-alpine
user: ${UID}:${UID}
working_dir: /home/node/app
volumes:
- ./frontend:/home/node/app
environment:
NODE_ENV: development
command: "npm run serve"
backend:
build:
context: dockerize/backend
# this way container interacts with host on behalf of current user.
# !!! NOTE: $UID is a _shell_ variable, not an environment variable!
# To make it available as a shell var, make sure you have this in your ~/.bashrc (./.zshrc etc):
# export UID="$UID"
user: ${UID}:${UID}
volumes:
- ./backend:/app
# custom adjustments to php.ini
# i. e. "xdebug.remote_host" to debug the dockerized app
- ./etc/php:/usr/local/etc/php/local.conf.d/
environment:
# add our custom config files for the php to scan
PHP_INI_SCAN_DIR: "/usr/local/etc/php/conf.d/:/usr/local/etc/php/local.conf.d/"
command: "php artisan serve --host=0.0.0.0 --port=8080"
mysql:
image: mysql:5.7.22
container_name: mysql
restart: unless-stopped
tty: true
ports:
- "4306:3306"
volumes:
- ./etc/mysql:/var/lib/mysql
environment:
MYSQL_DATABASE: tor
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_ROOT_PASSWORD: root
SERVICE_TAGS: dev
SERVICE_NAME: mysql
Add default.conf.nginx
server {
listen 81;
server_name frontend;
error_log /var/log/nginx/error.log debug;
location / {
proxy_pass http://frontend:8080;
}
location /sockjs-node {
proxy_pass http://frontend:8080;
proxy_set_header Host $host;
# below lines make ws://localhost/sockjs-node/... URLs work, enabling hot-reload
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /api/ {
# on the backend side, the request URI will _NOT_ contain the /api prefix,
# which is what we want for a pure-api project
proxy_pass http://backend:8080/;
proxy_set_header Host localhost;
}
}
Add Dockerfile
FROM php:fpm-alpine
RUN apk add --no-cache $PHPIZE_DEPS oniguruma-dev libzip-dev curl-dev \
&& docker-php-ext-install pdo_mysql mbstring zip curl \
&& pecl install xdebug redis \
&& docker-php-ext-enable xdebug redis
RUN mkdir /app
VOLUME /app
WORKDIR /app
EXPOSE 8080
CMD php artisan serve --host=0.0.0.0 --port=8080
DON'T FORGET TO ADD vue.config.js to your frontend folder
// vue.config.js
module.exports = {
// options...
devServer: {
disableHostCheck: true,
host: 'localhost',
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept'
},
watchOptions: {
poll: true
},
proxy: 'http://localhost/api',
}
}
Run sudo docker-compose up
If you want to do migrations run this: sudo docker-compose exec backend php artisan migrate
You will need 4 containers, defined in a docker-compose file:
frontend (your Vue application, which you already have)
backend (Laravel application)
web server (eg. Nginx or Apache)
database (MySQL)
It is possible to combine the 'web-server' and 'backend' containers into one, but this is generally bad advice.
Your compose file would look similar to this:
version: '3'
services:
frontend:
build: ./frontend
ports:
- 8080:8080
volumes:
- ./frontend:/app
backend:
build: ./backend
volumes:
- ./backend:/var/www/my_app
environment:
DB_HOST=db
DB_PORT=3306
webserver:
image: nginx:alpine
ports:
- 8000:8000
volumes:
- ./backend:/var/www/my_app
database:
image: mariadb:latest
container_name: db
ports:
- 3306:3306
environment:
MYSQL_DATABASE: dbname
MYSQL_ROOT_PASSWORD: dbpass
volumes:
- ./sql:/var/lib/mysql
where ./backend contains the Laravel application code, ./frontend contains the Vue application, and both contain a Dockerfile. Refer to Docker Hub for specific instructions on each image needed. This exposes 3 ports to your host system: 8080 (Vue app), 8000 (Laravel app), and 3306 (MySQL).
Alternatively, you can omit the web server if you use the artisan cli's serve command in your Laravel container, similar to what you're already doing in the Dockerfile for your Vue application.
The image would have to include something like CMD php artisan serve --host=0.0.0.0 --port=8000

Permissions problem with my first Laravel dev environment with Docker

I'm switching my development environments from virtual machines (with Vagrant and VirtualBox) to containers with Docker. I successfully set-up a simple dev environment for WordPress and now I'm trying to do the same for Laravel.
I'm on Windows 10 Pro, using WSL2 (Ubuntu 20.04 installed).
If I try to on on localhost:8088 (where my local Laravel installation is exposed) I get:
UnexpectedValueException
The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied
This is my docker-compose.yml file:
version: '3.3'
services:
nginx:
container_name: 'NGINX_Web_Server'
image: nginx:stable-alpine
depends_on:
- php
- mariadb
ports:
- 8088:80
volumes:
- ./root:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
php:
container_name: 'PHP-FPM_7.4'
build:
context: .
dockerfile: Dockerfile
volumes:
- ./root:/var/www/html
ports:
- 9090:9000
mariadb:
container_name: 'MariaDB_SQL_Server'
image: mariadb
restart: unless-stopped
tty: true
volumes:
- ./mariadb_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: laravel
MYSQL_USER: ll_user
MYSQL_PASSWORD: ll_password
this is the Dockerfile indicated in docker-compose.yml:
FROM php:fpm-alpine3.12
RUN docker-php-ext-install pdo pdo_mysql
#RUN chown -R www-data:www-data /var/www
and the default.conf file for nginx:
server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
What's wrong?
Could be solved with:
chown -R www-data:www-data /var/www
chmod -R 755 /var/www/storage
If it does not work for you, try this in the container:
Check: docker-compose exec php ls -al /var/www/storage
I saw xfs instead of www-data
Run: docker-compose exec php chown -R $USER:www-data /var/www/storage
Run: docker-compose exec php chown -R $USER:www-data /var/www/bootstrap/cache
Try again and it must work

Ngnix laravel docker project return error 502 bad gateway

I tried run laravel inside docker container with ngnix.
Directory structure:
File docker-compose.yml:
version: '3'
services:
nginx:
image: nginx:stable-alpine
container_name: nginx
ports:
- "${HOST_PORT}:80"
volumes:
- ../:/var/www/html
- ./etc/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
php:
build:
context: .
dockerfile: ../Dockerfile
restart: always
container_name: php
volumes:
- "../:/var/www/html"
ports:
- "9000:9000"
mongodb:
image: mongo:latest
container_name: mongodb
ports:
- "27017:27017"
redis:
image: redis:latest
container_name: redis
restart: always
ports:
- "6379:6379"
File Dockerfile:
FROM php:7.4-apache
RUN apt-get update && apt-get install --yes --no-install-recommends \
libssl-dev
RUN docker-php-ext-install pdo pdo_mysql
RUN pecl install mongodb \
&& docker-php-ext-enable mongodb
Result of command docker ps:
When I tried open in browser address http://localhost:8004 then get error:
502 Bad Gateway nginx/1.18.0
Ngnix config file:
server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
Env vars:
HOST_PORT=8004
HOST_SSL_PORT=3004
# Nginx
NGINX_HOST=localhost
As you're using nginx as your web-server, you don't need to install PHP Apache (FROM php:7.4-apache) in your Dockerfile.
Instead try php:7.4-fpm and make sure nginx accesses that php-fpm correctly (line fastcgi_pass php:9000; in your default.conf file. In your case everything seems configured correctly).
One more thing to note that it's not necessary to expose php-fpm port 9000 to the host machine. As both containers (in your docker-compose.yml) will use the same network, nginx container can directly access php container. You can remove the lines
ports:
- "9000:9000"

Resources