[Initial Commit]
This commit is contained in:
commit
6b55ae7c70
11 changed files with 360 additions and 0 deletions
6
.gitignore
vendored
Executable file
6
.gitignore
vendored
Executable file
|
@ -0,0 +1,6 @@
|
|||
.idea
|
||||
.DS_Store
|
||||
.env
|
||||
vendor
|
||||
public
|
||||
composer.lock
|
78
README.md
Executable file
78
README.md
Executable file
|
@ -0,0 +1,78 @@
|
|||
|
||||
# Docker PHP Development Environment
|
||||
|
||||
This repository allows you to quickly get a development environment up and running using Docker, including a MySQL database and some debugging tools.
|
||||
|
||||
This environment includes the latest versions of the following software:
|
||||
|
||||
- `nginx:alpine`
|
||||
- `php:8.3-fpm`
|
||||
- `mysql:latest`
|
||||
- `xdebug`
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker - https://www.docker.com/products/docker-desktop
|
||||
- Tested and confirmed working on:
|
||||
- macOS 12.3 (Monterey)
|
||||
- Windows 10 Version 21H1 build 19043.1165
|
||||
|
||||
## Project Setup
|
||||
|
||||
Run `composer create-project jlucki/docker-php-dev-env "project_name"`
|
||||
|
||||
Alternatively, download the files from this repo and copy them to your project directory.
|
||||
|
||||
## Running the Container
|
||||
|
||||
1. Run `docker compose up` from the project directory
|
||||
- Note: the above command will only work on versions newer than 3.6. If you are using Docker 3.6 or older, use `docker-compose up`
|
||||
2. Visit `localhost` in your browser
|
||||
|
||||
## Setting up Xdebug in Your IDE
|
||||
|
||||
_The following instructions are for PHPStorm._
|
||||
|
||||
1. Click on Run > Edit Configurations
|
||||
2. Click the `+` and add a new PHP Remote Debug configuration
|
||||
3. Give the configuration a name
|
||||
4. Tick _Filter debug connection by IDE key_
|
||||
5. Add `PHPSTORM` in the session id
|
||||
6. Click the `...` next to Server
|
||||
7. Click the `+` to add a new server
|
||||
8. Give the server a name, and set the host to `localhost`
|
||||
9. Tick _Use path mappings_
|
||||
10. Under the `Project files` file/directory, next to your project folder, for the `Absolute path on the server` column add `/var/www/html`
|
||||
11. Hit Apply and OK until you've returned to the IDE
|
||||
12. Click the _Start Listening for PHP Debug Connections_ icon
|
||||
13. Set a breakpoint in your code
|
||||
14. Refresh the page in your browser
|
||||
15. Accept _Incoming Connection From Xdebug_
|
||||
16. Happy debugging!
|
||||
|
||||
See https://xdebug.org/docs/remote for how to enable xdebug sessions.
|
||||
|
||||
## Additional Notes
|
||||
|
||||
For database connections, use `mysql` as the hostname. If you would like a different hostname, change the service name in the `docker-compose.yml` file.
|
||||
|
||||
## Windows 10 Troubleshooting
|
||||
|
||||
If you are having problems and can't seem to fix the issue, try one or both of these fixes:
|
||||
|
||||
### Solution 1
|
||||
Try switching to **Windows containers**:
|
||||
|
||||
Right-click the Docker icon in the system tray and click **Switch to Windows containers** as seen below:
|
||||
|
||||

|
||||
|
||||
### Solution 2
|
||||
If the **Use the WSL 2 based engine** setting is checked:
|
||||
|
||||
Uncheck the setting, then enable file sharing located under the **Resources** section, then the **File Sharing** section as seen below:
|
||||
|
||||

|
||||
|
||||
If the **Use the WSL 2 based engine** setting is unchecked:
|
||||
Enable/check the setting (file sharing is automatically configured)
|
31
composer.json
Executable file
31
composer.json
Executable file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "jlucki/docker-php-dev-env",
|
||||
"description": "A simple web development environment using Docker with NGINX, PHP, MySQL and Xdebug.",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"docker",
|
||||
"development",
|
||||
"environment",
|
||||
"php",
|
||||
"xdebug",
|
||||
"nginx"
|
||||
],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jan Lucki",
|
||||
"email": "jan@lucki.dev"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"sabre/dav": "^4.6",
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Keycloak": "src",
|
||||
"Collections": "src",
|
||||
"Principal": "src"
|
||||
}
|
||||
}
|
||||
}
|
24
docker-compose.yml
Executable file
24
docker-compose.yml
Executable file
|
@ -0,0 +1,24 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
web:
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- ./:/var/www/html
|
||||
- ./docker/conf/default.conf:/etc/nginx/conf.d/default.conf
|
||||
php:
|
||||
build:
|
||||
context: ./docker
|
||||
volumes:
|
||||
- ./:/var/www/html
|
||||
- ./docker/php/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
|
||||
mysql:
|
||||
image: mysql:latest
|
||||
ports:
|
||||
- "3306:3306"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: webapp
|
||||
MYSQL_USER: webapp
|
||||
MYSQL_PASSWORD: root
|
15
docker/Dockerfile
Executable file
15
docker/Dockerfile
Executable file
|
@ -0,0 +1,15 @@
|
|||
FROM php:8.3-fpm
|
||||
|
||||
ARG WITH_XDEBUG=true
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libfreetype6-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng-dev \
|
||||
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||
&& docker-php-ext-install -j$(nproc) gd \
|
||||
&& docker-php-ext-install mysqli \
|
||||
&& docker-php-ext-install pdo pdo_mysql; \
|
||||
if [ $WITH_XDEBUG = "true" ] ; then \
|
||||
pecl install xdebug; \
|
||||
fi ;
|
22
docker/conf/default.conf
Executable file
22
docker/conf/default.conf
Executable file
|
@ -0,0 +1,22 @@
|
|||
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/src;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri.js /index.php$is_args$args;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
6
docker/php/xdebug.ini
Executable file
6
docker/php/xdebug.ini
Executable file
|
@ -0,0 +1,6 @@
|
|||
[Xdebug]
|
||||
zend_extension=xdebug.so
|
||||
xdebug.mode=debug
|
||||
xdebug.client_port = 9000
|
||||
xdebug.client_host = host.docker.internal
|
||||
xdebug.idekey=PHPSTORM
|
40
index.php
Executable file
40
index.php
Executable file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use Collections\HomeCollection;
|
||||
use Sabre\DAV;
|
||||
|
||||
// The autoloader
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
$aclPlugin = new \Sabre\DAVACL\Plugin();
|
||||
|
||||
|
||||
// Set Auth
|
||||
$authBackend = new Keycloak\KeycloakAuth($aclPlugin,$_ENV['client_id'], $_ENV['client_secret'], $_ENV['keycloak_token_url'] );
|
||||
$authBackend->setRealm($_ENV['realm']);
|
||||
$authPlugin = new DAV\Auth\Plugin($authBackend);
|
||||
|
||||
|
||||
// The server object is responsible for making sense out of the WebDAV protocol
|
||||
$server = new DAV\Server([new HomeCollection($authPlugin, $_ENV['users_path'])]);
|
||||
|
||||
// If your server is not on your webroot, make sure the following line has the
|
||||
// correct information
|
||||
$server->setBaseUri($_ENV['base_uri']);
|
||||
|
||||
// The lock manager is responsible for making sure users don't overwrite
|
||||
// each others changes.
|
||||
$lockBackend = new DAV\Locks\Backend\File('data/locks');
|
||||
$lockPlugin = new DAV\Locks\Plugin($lockBackend);
|
||||
$server->addPlugin($lockPlugin);
|
||||
|
||||
|
||||
|
||||
// This ensures that we get a pretty index in the browser, but it is
|
||||
// optional.
|
||||
$server->addPlugin(new DAV\Browser\Plugin());
|
||||
$server->addPlugin($authPlugin);
|
||||
$server->addPlugin($aclPlugin);
|
||||
|
||||
// All we need to do now, is to fire up the server
|
||||
$server->start();
|
38
src/Collections/HomeCollection.php
Normal file
38
src/Collections/HomeCollection.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Collections;
|
||||
|
||||
use Sabre\DAV\Collection;
|
||||
use Sabre\DAV\Auth\Plugin as AuthPlugin;
|
||||
use Sabre\DAV\FS\Directory;
|
||||
|
||||
class HomeCollection extends Collection
|
||||
{
|
||||
private $plugin;
|
||||
private $userPath;
|
||||
|
||||
|
||||
public function __construct(AuthPlugin $authPlugin, $userPath)
|
||||
{
|
||||
$this->plugin = $authPlugin;
|
||||
$this->userPath = $userPath;
|
||||
}
|
||||
|
||||
public function getChildren()
|
||||
{
|
||||
$principal = $this->plugin->getCurrentPrincipal();
|
||||
$username = explode("/", $principal)[1];
|
||||
$path = $this->userPath;
|
||||
|
||||
if (!is_dir($path.$username)) {
|
||||
mkdir($path.$username, 0777 , true);
|
||||
}
|
||||
|
||||
return [new Directory($path.$username, $username)];
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return "Home";
|
||||
}
|
||||
}
|
56
src/Keycloak/KeycloakAuth.php
Normal file
56
src/Keycloak/KeycloakAuth.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Keycloak;
|
||||
|
||||
use Sabre\DAV\Auth\Backend\AbstractBasic;
|
||||
use Sabre\DAVACL\Plugin as AclPlugin;
|
||||
|
||||
class KeycloakAuth extends AbstractBasic
|
||||
{
|
||||
private $aclPlugin;
|
||||
private $client_id;
|
||||
private $client_secret;
|
||||
private $keycloakTokenUrl;
|
||||
|
||||
public function __construct(AclPlugin $plugin, $client_id, $client_secret, $keycloakTokenUrl)
|
||||
{
|
||||
$this->aclPlugin = $plugin;
|
||||
$this->client_id = $client_id;
|
||||
$this->client_secret = $client_secret;
|
||||
$this->keycloakTokenUrl = $keycloakTokenUrl;
|
||||
}
|
||||
|
||||
protected function validateUserPass($username, $password)
|
||||
{
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_URL => $this->keycloakTokenUrl,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "POST",
|
||||
CURLOPT_POSTFIELDS => "grant_type=password&client_id=" . $this->client_id . "&client_secret=" . $this->client_secret . "&username=".$username."&password=".$password,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Content-Type: application/x-www-form-urlencoded"
|
||||
],
|
||||
]);
|
||||
|
||||
curl_exec($curl);
|
||||
|
||||
$err = curl_error($curl);
|
||||
|
||||
$data = curl_getinfo($curl);
|
||||
|
||||
curl_close($curl);
|
||||
|
||||
if ($err || $data['http_code'] != 200) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
44
src/Principal/CustomBackend.php
Normal file
44
src/Principal/CustomBackend.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Principal;
|
||||
|
||||
use Sabre\DAVACL\PrincipalBackend\AbstractBackend;
|
||||
|
||||
class CustomBackend extends AbstractBackend
|
||||
{
|
||||
|
||||
public function getPrincipalsByPrefix($prefixPath)
|
||||
{
|
||||
// TODO: Implement getPrincipalsByPrefix() method.
|
||||
}
|
||||
|
||||
public function getPrincipalByPath($path)
|
||||
{
|
||||
// TODO: Implement getPrincipalByPath() method.
|
||||
}
|
||||
|
||||
public function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch)
|
||||
{
|
||||
// TODO: Implement updatePrincipal() method.
|
||||
}
|
||||
|
||||
public function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof')
|
||||
{
|
||||
// TODO: Implement searchPrincipals() method.
|
||||
}
|
||||
|
||||
public function getGroupMemberSet($principal)
|
||||
{
|
||||
// TODO: Implement getGroupMemberSet() method.
|
||||
}
|
||||
|
||||
public function getGroupMembership($principal)
|
||||
{
|
||||
// TODO: Implement getGroupMembership() method.
|
||||
}
|
||||
|
||||
public function setGroupMemberSet($principal, array $members)
|
||||
{
|
||||
// TODO: Implement setGroupMemberSet() method.
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue