Skip to content

Commit

Permalink
Merge pull request #21 from NoCompromises/docker-review
Browse files Browse the repository at this point in the history
merge in updates from recent projects and move to OrbStack
  • Loading branch information
joelclermont committed Jun 12, 2024
2 parents 0442177 + 955c756 commit 7e45c0a
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 78 deletions.
19 changes: 8 additions & 11 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
COMPOSE_PROJECT_NAME=my-project
DOCKER_SERVER_NAME=my-project.local

APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=https://my-project.test:30080

COMPOSE_PROJECT_NAME=my-project
DOCKER_MYSQL_LOCAL_PORT=33306
DOCKER_NGINX_LOCAL_PORT=30080
DOCKER_REDIS_LOCAL_PORT=36379
DOCKER_SERVER_NAME=my-project.test

SENTRY_LARAVEL_DSN=
SENTRY_TRACES_SAMPLE_RATE=1.0
SENTRY_SEND_DEFAULT_PII=true
APP_URL=https://my-project.local

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
Expand Down Expand Up @@ -66,3 +59,7 @@ VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

SENTRY_LARAVEL_DSN=
SENTRY_TRACES_SAMPLE_RATE=1.0
SENTRY_SEND_DEFAULT_PII=true
15 changes: 9 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
run: cp .env.example .env

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3

- name: Build Docker images
uses: docker/bake-action@v3
uses: docker/bake-action@v4
with:
load: true
files: |
Expand All @@ -36,7 +36,7 @@ jobs:
run: docker compose up -d mysql mysql-test php-fpm --wait --no-build

- name: Cache composer dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: vendor
key: composer-${{ hashFiles('composer.lock') }}
Expand All @@ -54,7 +54,7 @@ jobs:
docker inspect "$PROJECT_NAME-mysql"
- name: Cache npm dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: node_modules
key: npm-${{ hashFiles('package-lock.json') }}
Expand All @@ -65,22 +65,25 @@ jobs:
- name: Install JS dependencies
run: npm install && npm run build

- name: Run JS test suite
run: LARAVEL_BYPASS_ENV_CHECK=1 npm test

- name: Cache routes
run: docker exec "$PROJECT_NAME-php-fpm" ./artisan route:cache

- name: Cache views
run: docker exec "$PROJECT_NAME-php-fpm" ./artisan view:cache

- name: Cache Larastan result cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: .phpstan.cache
key: "phpstan-result-cache-${{ github.run_id }}" # always unique key - always writes a new cache
restore-keys: | # prefix allows it to use previous cache as starting point
phpstan-result-cache-
- name: Cache php-cs-fixer result cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: .php-cs-fixer.cache
key: "php-cs-fixer-result-cache-${{ github.run_id }}" # always unique key - always writes a new cache
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ You can also remove:
Modifications are needed to the following files already in a default Laravel install:

* `.env.example` and `.env`
* copy from `APP_URL`, `COMPOSER_PROJECT_NAME`, `DOCKER_MYSQL_LOCAL_PORT`, `DOCKER_NGINX_LOCAL_PORT`, and `DOCKER_SERVER_NAME`
* copy from `APP_URL`, `COMPOSE_PROJECT_NAME`, and `DOCKER_SERVER_NAME`
* copy `DB_HOST`, `DB_DATABASE`, `DB_USERNAME`, and `DB_PASSWORD`

Update your Composer packages and scripts:
Expand Down
30 changes: 17 additions & 13 deletions README_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,20 @@ To get started with local development, follow these steps. Make sure you run all

### DNS resolution

> Decide on a local domain to use for this project. Substitute that any place you see `my-project.test` or `my-project` below.
> Decide on a local domain to use for this project. Substitute that any place you see `my-project.local` or `my-project` below.
By default, this project will run on the host `my-project.test`. This requires some sort of local DNS resolution for that hostname
to your localhost IP address. One easy way to do this for the entire `.test` top-level domain, is to run a lightweight tool
called `dnsmasq`. You can install it via Homebrew on a Mac with: `brew install dnsmasq`.
By default, this project will run on the host `my-project.local`.
OrbStack (see below) is already configured to serve on this top-level domain.

If you're not using OrbStack, you will need some sort of local DNS resolution for that hostname to your localhost IP address.
One easy way to do this for the entire `.local` top-level domain, is to run a lightweight tool called `dnsmasq`.
You can install it via Homebrew on a Mac with: `brew install dnsmasq`.

> If you've ever setup Valet, it already installed dnsmasq for you. You can verify if it's already installed by running
> `brew services` and see if `dnsmasq` is listed.
If you don't want to run `dnsmasq`, you can also add a manual DNS entry to your `/etc/hosts` file in the form:
`127.0.0.1 my-project.test`
`127.0.0.1 my-project.local`

### Setting up an SSL certificate

Expand All @@ -56,22 +59,23 @@ Once `mkcert` is installed, we need to generate our local development root certi

Then, generate the certificates for this project and put them into a location accessible to your docker setup:

`mkcert -cert-file docker/nginx/ssl.pem -key-file docker/nginx/key.pem my-project.test`
`mkcert -cert-file docker/vite/ssl.pem -key-file docker/vite/key.pem my-project.test`

### Node environment
The best option to ensure you're using the correct versions of Node and npm with this project is to install [Volta](https://volta.sh). Volta will read the pinned versions of Node and npm from the `package.json` so you can be sure you're using the correct versions.
The best option to ensure you're using the correct versions of Node and npm with this project is to install [Volta](https://volta.sh).
Volta will read the pinned versions of Node and npm from the `package.json` so you can be sure you're using the correct versions.

### Get the project running in Docker

Docker is used for local development. It's self-contained, easy to set up, and matches the exact versions of key services
running in production. It requires that you have [Docker Desktop](https://www.docker.com/products/docker-desktop/) installed.
running in production. We use [OrbStack](https://orbstack.dev) as our Docker engine, since it handles domain resolution and port mapping.
This config also works with [Docker Desktop](https://www.docker.com/products/docker-desktop/), but you may need to add explicit port mappings.

**Setup the environment**

Make a copy of the example env file: `cp .env.example .env`
Open the `.env.example` file and update the `COMPOSE_PROJECT_NAME` and `DOCKER_SERVER_NAME` settings to match your project.

Open the `.env` file and review the settings prefixed with `DOCKER_`. The defaults should work, but if you want a different
host name, or to change the port numbers, make those modifications before continuing with the Docker setup.
Make a copy of the example env file: `cp .env.example .env`

**Get Docker running**

Expand All @@ -97,7 +101,7 @@ And then open `auth.json` and fill out the username and password values.
**Normal project setup**

With the certificates, our environment, and Docker setup, the rest of these steps will be typical steps for any Laravel
project. The one key difference is that instead of running tools like npm, composer and artisan directly, we need to run
project. The one key difference is that instead of running tools like composer and artisan directly, we need to run
them from inside the container. This is very important. If we run the tools from our host environment, all the guarantees
about versions of tooling will no longer apply.

Expand All @@ -112,7 +116,7 @@ Run these commands to finish the local development setup
* `docker/bin/artisan horizon:install`
* `docker/bin/artisan migrate --seed`

You're good to go - surf to https://my-project.test:30080 (or a different host/port if you've configured it)
You're good to go - surf to https://my-project.local

You can also use any normal database management tools and connect to the database using the port specified in `.env`.

Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "nocompromises/my-project",
"version": "1.0.0",
"type": "project",
"license": "proprietary",
"require": {
Expand Down
52 changes: 25 additions & 27 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,49 @@
## - Make sure to enable the performance optimization for Macs, if you're running on macOS 12.2 or higher.
## From Docker Desktop, go to Settings, Experimental Features and enable both settings for virtualization and VirtioFS.
########################################################################################################################
version: "3.9"

services:

## The App database
mysql:
container_name: "${COMPOSE_PROJECT_NAME}-mysql"
image: mysql:8.0.35
image: mysql:8.0.37
volumes:
- mysql-data:/var/lib/mysql
- ./docker/mysql/init:/docker-entrypoint-initdb.d
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=app # update .env and .env.example if you change any of these values
- MYSQL_USER=app
- MYSQL_PASSWORD=app
ports:
- "${DOCKER_MYSQL_LOCAL_PORT}:3306"
command:
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
- "--default-authentication-plugin=mysql_native_password"
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: app # update .env and .env.example if you change any of these values
MYSQL_USER: app
MYSQL_PASSWORD: app
# Uncomment the command section if you need to deviate from MySQL defaults (like on a legacy database schema)
# command:
# - "--character-set-server=utf8mb4"
# - "--collation-server=utf8mb4_0900_ai_ci"
# - "--default-authentication-plugin=caching_sha2_password"
restart: unless-stopped

## MySQL just for Unit Tests
mysql-test:
container_name: "${COMPOSE_PROJECT_NAME}-mysql-test"
image: mysql:8.0.35
image: mysql:8.0.37
volumes:
- mysql-test-data:/var/lib/mysql
- ./docker/mysql/init:/docker-entrypoint-initdb.d
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=apptest # update phpunit.xml if you change any of these values
- MYSQL_USER=app
- MYSQL_PASSWORD=app
command:
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
- "--default-authentication-plugin=mysql_native_password"
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: apptest # update phpunit.xml if you change any of these values
MYSQL_USER: app
MYSQL_PASSWORD: app
# Uncomment the command section if you need to deviate from MySQL defaults (like on a legacy database schema)
# command:
# - "--character-set-server=utf8mb4"
# - "--collation-server=utf8mb4_0900_ai_ci"
# - "--default-authentication-plugin=caching_sha2_password"
restart: unless-stopped

redis:
container_name: "${COMPOSE_PROJECT_NAME}-redis"
image: redis:7.0.5-alpine3.17
ports:
- "${DOCKER_REDIS_LOCAL_PORT}:6379"
image: redis:7.2.5-alpine3.20
restart: unless-stopped

## NGINX to support the app, configured to use the php-fpm-debug server
Expand All @@ -71,8 +69,8 @@ services:
working_dir: /app
volumes:
- .:/app
ports:
- "${DOCKER_NGINX_LOCAL_PORT}:443"
labels:
- "dev.orbstack.domains=${DOCKER_SERVER_NAME}"
depends_on:
- php-fpm-debug
restart: unless-stopped
Expand Down
4 changes: 1 addition & 3 deletions docker/nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
FROM nginx:1.22.0-alpine
FROM nginx:1.27.0-alpine3.19

COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY ssl.pem /etc/nginx/ssl.pem
COPY key.pem /etc/nginx/key.pem
19 changes: 13 additions & 6 deletions docker/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl.pem;
ssl_certificate_key /etc/nginx/key.pem;
listen 80;
root /app/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;

if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}

location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass php-fpm-debug:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_read_timeout 300;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
6 changes: 3 additions & 3 deletions docker/php-fpm/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM php:8.2.12-fpm-alpine3.18 as base
FROM php:8.3.8-fpm-alpine3.20 as base

RUN apk add --no-cache $PHPIZE_DEPS \
freetype-dev \
Expand All @@ -17,13 +17,13 @@ RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
RUN pecl install redis-6.0.2 && docker-php-ext-enable redis

# install composer from the composer image
COPY --from=composer:2.6.5 /usr/bin/composer /usr/bin/composer
COPY --from=composer:2.7.7 /usr/bin/composer /usr/bin/composer

COPY docker-php-file-uploads.ini /usr/local/etc/php/conf.d/docker-php-file-uploads.ini

FROM base as debug

# Supports xdebug
RUN apk add --update linux-headers
RUN pecl install xdebug-3.2.2 && docker-php-ext-enable xdebug
RUN pecl install xdebug-3.3.2 && docker-php-ext-enable xdebug
COPY docker-php-ext-xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
2 changes: 1 addition & 1 deletion docker/php-fpm/docker-php-ext-xdebug.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
zend_extension=xdebug
xdebug.mode=debug
xdebug.mode=debug,develop
xdebug.idekey=PHPSTORM
xdebug.client_host=docker.for.mac.localhost
memory_limit=512M
Expand Down
1 change: 1 addition & 0 deletions docker/vite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pem
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"dev": "vite",
"build": "vite build",
"lint": "eslint ./resources/js",
"test": "vitest",
"test-with-coverage": "vitest run --coverage"
"test": "vitest --passWithNoTests",
"test-with-coverage": "vitest run --coverage --passWithNoTests"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.5.2",
Expand Down
8 changes: 3 additions & 5 deletions vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,13 @@ export default defineConfig(({ mode }) => {

if (mode === "development") {
config.server = {
port: 30098,
strictPort: true,
host: true,
https: {
key: readFileSync("docker/nginx/key.pem"),
cert: readFileSync("docker/nginx/ssl.pem"),
key: readFileSync("docker/vite/key.pem"),
cert: readFileSync("docker/vite/ssl.pem"),
},
hmr: {
host: "project.domain",
host: "my-project.test",
},
};
}
Expand Down

0 comments on commit 7e45c0a

Please sign in to comment.