Open Natetronn opened 5 months ago
maybe changing https_port in Caddyfile? https://caddyserver.com/docs/caddyfile/options#https-port
auto_https disable_redirects
can be set as a global option in Caddy. Then you can set the server_name to something like :8095
Thanks for the replies!
I wasn't able to figure anything further using those suggestions, however, I got it working on Linux by setting the IP address in /etc/hosts using the container's IP address instead of 127.0.0.1, as I had before.
On Windows with Docker Desktop (in WSL2 mode) I couldn't get it working with changed host ports unless I used the port in the url too. So one could add the various ports to that url or just use one container at a time and stick to the default host ports like so:
ports:
- 80:80
- 443:443
- 443:443/udp
If anyone wants to play around here's what I have so far:
docker-compose.yml
version: "3.8"
services:
frankenphp:
container_name: mydomain
# image: dunglas/frankenphp
build: .
restart: unless-stopped
ports:
- 8081:80
- 4434:443
- 4434:443/udp
volumes:
- ./public:/app/public
- ./caddy/data:/data
- ./caddy/config:/config
- ./caddy/certs:/certs
- ./caddy/log:/var/log
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
environment:
# sets the domain in Caddyfile - make sure to use the same domain when creating your self-signed certificates
- DOMAIN=mydomain.loc
Dockerfile
FROM dunglas/frankenphp:latest-php8.3.4-alpine
# Add additional PHP extensions or Composer
# https://frankenphp.dev/docs/docker/#how-to-install-more-php-extensions
# https://github.com/mlocati/docker-php-extension-installer
# https://github.com/mlocati/docker-php-extension-installer?tab=readme-ov-file#supported-php-extensions
# https://github.com/mlocati/docker-php-extension-installer?tab=readme-ov-file#installing-composer
RUN install-php-extensions gd xdebug yaml
Caddyfile
{
# Enable FrankenPHP
frankenphp
# Configure when the directive must be executed
order php_server before file_server
}
{$DOMAIN} {
# Enable logging; update as needed - https://caddyserver.com/docs/caddyfile/directives/log
# log {
# output file /var/log/access.log
# }
# tls internal works, but https cert won't be valid; use your own self-signed certs instead if you want https
# tls internal
# Generate your own self-signed certificates using mkcert or similar - set the URL environment variable to the same domain name
tls /certs/{$DOMAIN}.cert.pem /certs/{$DOMAIN}.key.pem
# Serve static files
root * /app/public
# Enable compression (optional)
encode zstd br gzip
# Execute PHP (FrankenPHP) in the aboven root directory and serve assets
php_server
}
/etc/hosts
172.XXX.X.X mydomain.loc
or
c:\Windows\System32\drivers\etc\hosts
127.0.0.1 mydomain.loc
Note: you can find the IPAddress using docker inspect <Container ID or Name> | grep IPAddress
or just docker inspect <Container ID or Name>
. You can also find it in Portainer or Docker Desktop (I think under Inspect tab > network).
To create certs you can use one of these scripts:
create-certs.sh (requires mkcert and possibly nss)
#!/usr/bin/env bash
# Parameters
# Set DOMAIN variable to the value of the first positional parameter,
# or default to "localhost" if no parameter is provided
DOMAIN="${1:-localhost}"
# Set CERTS_DIR variable to the value of the second positional parameter,
# or default to "./certs" if no parameter is provided
CERTS_DIR="${2:-./certs}"
# File names
CERT_PEM_FILE="${CERTS_DIR}/${DOMAIN}.cert.pem"
KEY_PEM_FILE="${CERTS_DIR}/${DOMAIN}.key.pem"
# first ensure required executables exists:
if [[ `which mkcert` == "" ]] || [[ `nss-config nss --version` == "" ]]; then
echo "Requires: mkcert & nss"
echo
echo "Run: sudo pacman -S mkcert nss"
exit 1
fi
# finally install certificates
echo "-- Installing mkcert ..."
mkcert -install
mkdir -p ${CERTS_DIR}
echo "-- Creating and installing local SSL certificates for domain: ${DOMAIN} ..."
mkcert -cert-file ${CERT_PEM_FILE} -key-file ${KEY_PEM_FILE} "${DOMAIN}"
echo "-- Complete!"
echo
echo "- Now you can run: docker compose up -d"
echo "- Open browser to domain: https://${DOMAIN}"
create-certs.bat (requires choco and mkcert)
@echo off
REM parameters
SET DOMAIN=%1
IF "%DOMAIN%"=="" SET DOMAIN=localhost
SET CERTS_DIR=%2
IF "%CERTS_DIR%"=="" SET CERTS_DIR=.\certs
SET CERT_PEM_FILE=%CERTS_DIR%\%DOMAIN%.cert.pem
SET KEY_PEM_FILE=%CERTS_DIR%\%DOMAIN%.key.pem
REM Check if mkcert is installed
where mkcert >nul 2>nul
IF %ERRORLEVEL% NEQ 0 (
echo Requires: mkcert
echo.
echo Run: choco install mkcert
exit /b 1
)
REM Finally install certificates
echo -- Installing mkcert ...
mkcert -install
mkdir %CERTS_DIR%
echo -- Creating and installing local SSL certificates for domain: %DOMAIN% ...
mkcert -cert-file %CERT_PEM_FILE% -key-file %KEY_PEM_FILE% "%DOMAIN%"
echo -- Complete!
echo.
echo - Now you can run: docker compose up -d
echo - Open browser to domain: https://%DOMAIN%
Either script will take a domain (mydomain.loc for example) for the first parameter and an output path for the second.
Interesting. I use Windows Docker with WSL. But I typically just map different ports to different apps that I want to run.
App 1: 8090:80
App 2: 8091:80
etc then I just run localhost:8090 or localhost:8091
Is there a reason why you need certs locally? Doesn't seem like you would need to manage a custom caddyfile if you could avoid the cert requirement for local dev. Every place is unique but I try to avoid local cert management on windows whenever possible.
@Natetronn I use DDEV instead of XAMPP/MAMP that seems allot simpeler just for a dev environment.
But it is also possible with caddy reverse proxy and your host file i think.
With a reverse proxy from caddy it uses a internal port of the container not an exposed port in the host machine:
so in the Caddyfile from your caddy network there would be something like this:
url.com { reverse_proxy dockercontainername:80 }
for the frankenphp container make sure it is not creating an ssl certificate because your caddy network does that for you.
services: php: image: dunglas/frankenphp restart: always networks:
- caddy_caddy <- use the network that your caddy router is listening on environment: SERVER_NAME: :80
@Asociateone thanks for the suggestion!
I am familiar with ddev (and Devilbox et al.), but I wanted to move in a different direction; one that is a bit more minimal, where you only add the things you need, not a full blown system with opinions, where I won't use half the stuff included. Also, I want it more portable, where I can use the same or mostly the same setup locally and then also on the production side (like on DO or Linode etc.)
Aside: this reminds me, I maintain the Docksal AUR package even though I don't personally use it. I should check on that.
I already had a "normal" docker php / caddy setup working that is similar to frankenphp, but frankenphp was slightly less complicated (or so I thought) in that it was all wrapped up in one container, so I was trying to move to that for the sake of simplicity and others. I even had docker php extension installer working, which is one of the pros of frankenphp.
With that said, not sure it would make sense at that point to even use frankenphp (if I was moving to a standalone caddy). But I'll think about it...and now that I'm thinking of it, frankenphp does have some other features to consider, like performance, for example, so maybe still something to consider.
@StephenMiracle sorry for the late response. Yeah, for sure...I don't really NEED local certs, but it was more of a nice to have kind of WANT; trying to get as close to the real thing as possible kind of thing.
In regards to Windows, yeah, I use Linux myself lol. I do, however, have Windows (dual boot) setup for testing this kind of stuff. And I have some friends and colleagues who use Windows and my attempt to resolve this was really for their sake. Everything was working as I wanted on my side, but not on the Windows side. And, well, sometimes I get going down a path and just don't know when to give up, I guess lol
And on that note, I'll leave this open for now, in case anyone wants to continue the conversation, but this is mostly a non-issue at this point, so don't feel the need to keep trying to solve this; unless you want to, of course. I've mostly moved on, though.
Anyway, I really appreciate everyone suggestions and insights!
Anyway, I really appreciate everyone suggestions and insights!
Did you found any solution? what you think about this:
docker-compose.yml
services:
php:
working_dir: /app
environment:
- ENV REQUEST_MAX_EXECUTION_TIME=0
- HTTP_PORT=8080
- HTTPS_PORT=8443
- SERVER_NAME=localhost:${HTTP_PORT}
build:
context: .
dockerfile: Dockerfile
volumes:
- ./:/app
- ./Caddyfile:/etc/caddy/Caddyfile
ports:
- 8080:8080
- 8443:8443
php-2:
working_dir: /app
environment:
- ENV REQUEST_MAX_EXECUTION_TIME=0
- HTTP_PORT=8081
- HTTPS_PORT=8444
- SERVER_NAME=localhost:${HTTP_PORT}
build:
context: .
dockerfile: Dockerfile
volumes:
- ./:/app
- ./Caddyfile:/etc/caddy/Caddyfile
ports:
- 8081:8081
- 8444:8444
Dockerfile
FROM dunglas/frankenphp:latest-alpine
RUN apk add --no-cache git
RUN install-php-extensions \
pdo_mysql \
gd \
intl \
zip
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
ARG USER=application
ARG UID=1000
RUN addgroup -g ${UID} ${USER}; \
adduser -D -u ${UID} -G ${USER} ${USER}; \
chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy;
USER ${USER}
ARG HTTP_PORT=8080
ARG HTTPS_PORT=8443
EXPOSE ${HTTP_PORT} ${HTTPS_PORT}
ENV HTTP_PORT=${HTTP_PORT}
ENV HTTPS_PORT=${HTTPS_PORT}
Caddyfile
{
{$CADDY_GLOBAL_OPTIONS}
http_port {$HTTP_PORT:80}
https_port {$HTTPS_PORT:443}
frankenphp {
{$FRANKENPHP_CONFIG}
}
# https://caddyserver.com/docs/caddyfile/directives#sorting-algorithm
order mercure after encode
order vulcain after reverse_proxy
order php_server before file_server
order php before file_server
}
{$CADDY_EXTRA_CONFIG}
{$SERVER_NAME:localhost} {
root * public/
encode zstd br gzip
{$CADDY_SERVER_EXTRA_DIRECTIVES}
php_server
}
Using this way you can have multiple https://localhost (using different ports)
Hello!
Does anyone know how to run multiple containers of FrankenPHP at the same time?
I'd like to use it for local dev environment instead of XAMPP (WAMP/MAMP et al.) and this for a bunch of different projects; that all live in different directories and will all use different containers (if possible.)
If I'm not mistaken, after some research, Caddy requires the host's ports 80 and 443 for ACME Cert reasons. So changing those to, say, 8080:80 and 4443:443 doesn't work. (?) I'm using custom testing domains that I set in /etc/hosts (host side) and then in the Caddyfile. That works fine, as long as I keep the ports as is, but if I change the ports to allow for multiple containers it no longer works.
Aside: I tried, but don't know how to run
php_server
andreverse_proxy localhost:4443
at the same time or if it's even possible, thinking that might lead to a possible solution.Turning off and on containers isn't the end of the world, but it's less than ideal. With that said, is there a better way to manage a bunch of projects with FrankenPHP all running at the same time?
Appreciate any suggestions, thank you!