#Deploying my first app to Hetzner Cloud

31 messages · Page 1 of 1 (latest)

velvet swallow
#

I have a potentially dumb question. Bear with me, I may sound stupid but this is my first time doing this crap and I would appreciate your help. I know you don't get anything from helping me, so thank you in advance. I have a Nuxt SSR and a Laravel API. Laravel uses serversideup's image which has its own fpm and nginx configuration. Now I need Nginx on host (so outside of docker containers) to make a proxy or something so the user communicates with Nuxt and Nuxt communicates with the api (I have set my domains and I have set my certificate). Now in my Nginx config do I use the localhost for proxying or the container names? And what else should I know for this? This has been a pain tbh

This is my doocker-compose.prod for these 2 containers :

version: '3.9'

services:
  mysql:
    image: mysql:8.0
    container_name: sql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydb
      MYSQL_USER: myuser
      MYSQL_PASSWORD: somepassword
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - app-net

  api:
    build:
      context: ./laravel-api
      dockerfile: Dockerfile
    container_name: api
    restart: unless-stopped
    env_file: ./laravel-api/.env.prod
    depends_on:
      - mysql
    ports:
      - "127.0.0.1:8080:8080"
    networks:
      - app-net

  nuxt:
    build:
      context: ./nuxt-app
      dockerfile: Dockerfile.prod
      target: prod
    container_name: nuxt
    restart: unless-stopped
    environment:
      - NODE_ENV=production
    ports:
      - "127.0.0.1:3000:3000"
    networks:
      - app-net

networks:
  app-net:
    driver: bridge

volumes:
  mysql_data:
#

Also here are my Nginx HOST configurations(this was done by dumb ai, I dont believe this is correct):
Laravel api:

server {
    listen 80;
    server_name api.myaddress.app;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}```

Front nginx :
```php
server {
    listen 80;
    server_name domain1.app www.domain.app;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        'upgrade';
        proxy_set_header Host              $host;
        proxy_cache_bypass                 $http_upgrade;
    }
}

My dockerfile for backend:

FROM serversideup/php:8.3-fpm-nginx

# 1. Set working dir
WORKDIR /var/www/html

# 2. Copy composer manifests, install PHP deps
COPY composer.json composer.lock ./
RUN composer install \
      --no-dev \
      --optimize-autoloader \
      --prefer-dist \
      --no-interaction \
      --no-scripts

# 3. Copy the rest of the application (as www-data)
COPY --chown=www-data:www-data . .

# 4. Ensure storage & cache dirs exist, owned by www-data
RUN mkdir -p storage/logs bootstrap/cache \
    && chown -R www-data:www-data storage bootstrap/cache \
    && chmod -R 755 storage bootstrap/cache

# 5. Expose the HTTP port (handled by the base image)
EXPOSE 80

# 6. Entrypoint/CMD—and base image will start php-fpm + nginx for you
#

My dockerfile for frontend :

# syntax=docker/dockerfile:1

# 1. Install only production dependencies
FROM node:22-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev

# 2. Build the application
FROM node:22-alpine AS build
WORKDIR /app
# copy prod deps and source
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

# 3. Production image
FROM node:22-alpine AS prod
WORKDIR /app
# copy deps and build output
COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/.output ./.output

# expose the Nuxt server port
EXPOSE 3000

# launch the app
CMD ["node", ".output/server/index.mjs"]
limpid adder
#

when routing network traffic within the docker compose you should use container names, really you'd be better off adding a traefik service and only exposing that

#

then just add labels to tell traefik how to route stuff

#

it'll also sort ssl for you

velvet swallow
#

I never did traefik and tbh first time hearing that

#

So is it something like this: ```php
log:
level: INFO

entryPoints:
web:
address: ":80"
websecure:
address: ":443"

providers:
docker:
exposedByDefault: false

certificatesResolvers:
leresolver:
acme:
email: you@example.com
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web```

limpid adder
#

For the yaml config yeah but then you've got to add labels to your containers

velvet swallow
#

So a directory with : front, back, traefik, docker-compose?

velvet swallow
# limpid adder <https://doc.traefik.io/traefik/getting-started/quick-start/>

When looking at the docs, this could be bad then ?

ervices:
  traefik:
    image: traefik:v3.0
    command:
      - --providers.docker=true
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.leresolver.acme.httpchallenge=true
      - --certificatesresolvers.leresolver.acme.httpchallenge.entrypoint=web
      - --certificatesresolvers.leresolver.acme.email=email@gmail.com
      - --certificatesresolvers.leresolver.acme.storage=/letsencrypt/acme.json
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./traefik:/letsencrypt
    networks:
      - app-net

  nuxt:
    build:
      context: ./nuxt-app
      dockerfile: Dockerfile.prod
      target: prod
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nuxt.rule=Host(`domain`,`www.domain`)"
      - "traefik.http.routers.nuxt.entrypoints=websecure"
      - "traefik.http.routers.nuxt.tls.certresolver=leresolver"
      - "traefik.http.services.nuxt.loadbalancer.server.port=3000"
    networks:
      - app-net

  api:
    build:
      context: ./laravel-api
      dockerfile: Dockerfile
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.domain`)"
      - "traefik.http.routers.api.entrypoints=websecure"
      - "traefik.http.routers.api.tls.certresolver=leresolver"
      - "traefik.http.services.api.loadbalancer.server.port=80"
    networks:
      - app-net```
limpid adder
#

wdym this could be bad then??

#

also you probably want an internal network for your containers, then only expose traefik to both the default and the internal

velvet swallow
#

Man what the hell, I got tons of crap to learn and I dont know where to begin and where to look

#

Is there something on Laracasts that could help? I feel dumb as hell

#

Dont I miss the labels to enforce https tho?

velvet swallow
# limpid adder wdym this could be bad then??

Well I am not enforcing https, I got two parameters for hosts in label for nuxt, I need to use a regex, I have set ports, do I even need them or I can just do expose? I need to set internal to true for networks so it does that what you said? My Laravel URL gives 502, while my Nuxt gives 404, this is madness

limpid adder
velvet swallow
#

Okay did that, now I still get 502 with Laravel nothing in the logs...

limpid adder
#

that's a 502 bad gateway so it's not even hitting your laravel service

#

look at the traefik logs, you can bump the log level to debug if needed

velvet swallow
#

Would this stop me from running composer install? networks:
web:
internal-net:
internal: true

velvet swallow
#

What could be the reason why my composer install isn't running in the docker file?

velvet swallow
#

Never mind I am dumb, I run composer install then copy the directory which gets overrun then...

velvet swallow
#

I screwed everything up...

velvet swallow
#

Do I need pihole in this situation? Ive been following this tutorial https://technotim.live/posts/traefik-3-docker-certificates/

Techno Tim

In today’s Traefik tutorial we’ll get FREE Wildcard certificates to use in our HomeLab and with all of our internal self-hosted services. We’re going to set up Traefik 3 in Docker and get Let’s Encrypt certificates using Cloudflare as our DNS Provider (we’ll cover how to set up others too). Then we’ll configure local DNS using PiHole...

limpid adder
velvet swallow
#

Thank you also for your help and sorry for my stupidity...