Skip to content

Feature: Improve Development Setup#795

Merged
edwh merged 33 commits intoTheRestartProject:developfrom
iFixit:improve-development-setup
Jun 16, 2025
Merged

Feature: Improve Development Setup#795
edwh merged 33 commits intoTheRestartProject:developfrom
iFixit:improve-development-setup

Conversation

@ardelato
Copy link
Contributor

@ardelato ardelato commented Apr 3, 2025

Description

This pull request introduces two major changes to enhance the local development setup for the Restarters project.

The changes include:

  • The addition of a new Taskfile.yml for task management
  • Updating the docker-compose.yml file to support different development profiles

In addition, I've added documentation surrounding these changes.

CR Notes:

Commit 703d8b6 goes over the reason for choosing Task as opposed to a bash script or Makefile.

By utilizing Docker Compose Profiles we can customize which services we would spin up locally. That way we do not utilize more resources than needed for local development.

As for the documentation, it goes over the prerequisites and setup for local development, as well as examples of how to run frequent actions. That said, I added the document to /docs but I am not sure if that is the correct location for it.

ardelato added 11 commits April 3, 2025 11:32
…files

- Introduced docker-compose.dev.yml for development services including
phpMyAdmin and Mailhog.
- Added docker-compose.discourse.yml for Discourse services including
PostgreSQL, Redis, and Sidekiq.
- Removed existing phpMyAdmin and Discourse configurations from
docker-compose.yml to streamline service management.

By extracting these services into separate files we can build up the
stack on a case by case basis. This will free up host machines resources
and make it easier to manage the development environment.

I will be creating some development scripts in the future to help
with the setup and tearing down of the development environment.
This cleans up the comments in the docker-compose files since I had
originally created each docker-compose file by `cp docker-compose.yml`.

Some of the comments were removed in some of the files because they
referenced services that were not present in the file. Additionally,
I refactored some of the comments to be more linear and easier to read.
Taskfile.yml was chosen over Makefile primarily because its YAML syntax
is significantly easier to read and understand. This improves
maintainability and makes it more approachable to folks who may not
be familiar with the syntax of Makefiles. Additionally, Taskfile is
also designed as a general task runner, unlike the build-focused
nature of Makefiles. This makes it a better fit for managing
diverse workflows, automating steps, and helper functions
beyond just compilation. For now though, we will only be using it
to manage the Docker containers while we work on refactoring the app
setup process.

That said, we could have gone with bash scripts to manage these tasks,
but bash scripts become increasingly difficult to manage and read
as the logic grows. Writing intricate functions, handling argument
parsing, implementing error checking, and managing dependencies between
steps often leads to bash code that is verbose, hard to follow, and
challenging to debug and maintain. Taskfile provides a more structured
and familiar syntax to orchestrate the tasks.
Taskfiles allow the use of wildcards to pass arguments as part of the
task name. This allows us to reduce the number of tasks since we don't
need to create a task for each combination of containers we want to start
or stop. For example, docker:up:dev, docker:up:discourse, etc.

One caveat is that Taskfiles do not currently support lazy variable
lookup. As such, we can't save the output of a dependent task to a
variable and reuse it in a subsequent task. This is a bit of a pain,
but for our use case, we can live with it. The workaround then was to
use a map variable to act as a switch statement to determine which stack
to start or stop in line. This requires the map experimental feature to be
enabled, which we have done via the .env file.
Similar to the prior commits, let's add a task for rebuilding the Docker containers.
By leveraging YAML anchors and variables, we can dedupe a lot of the
task configurations for the docker wildcard tasks.
Similar to the prior commits, let's add a task for restarting the Docker containers.
This adds some miscellaneous tasks that will be useful for development,
such as following the logs of the main app container, opening a shell into
the container, and running specific commands within the container.
Some folks, or machines, may still be using an older version of Docker
where Docker Compose has not been fully integrated into Docker. As such,
we should check if the docker-compose command exists and use that
for all docker compose commands. Otherwise, we will use
the docker compose command.
Instead of using multiple docker-compose files, we can use docker compose
profiles to build up the stack on a case by case basis. This will simplify
things since there will only be one docker-compose file, while we can
still retain the ability to configure the different services as needed.
@edwh edwh self-assigned this Apr 7, 2025
@edwh edwh self-requested a review April 7, 2025 08:56
@edwh edwh removed their assignment Apr 7, 2025
@edwh edwh requested a review from Copilot April 7, 2025 08:56
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • .env.example: Language not supported
Comments suppressed due to low confidence (1)

docs/local-development.md:25

  • The line containing '****' appears extraneous and could lead to formatting issues in the rendered documentation. Consider removing it to improve clarity.
****

Copy link
Collaborator

@edwh edwh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally this is looking excellent. But a few comments and I'm not sure it's ready to merge yet.

@edwh
Copy link
Collaborator

edwh commented Apr 14, 2025

Couple of other things from testing.

  1. On Windows, I see this log

image

Possibly for this reason, when I changed some of front-end code (e.g. DashboardPage) and refreshed, the change never got picked up. I can't remember if this was a problem with our original docker setup - it's been a while since I used it. Do code changes work for you?

  1. You might not have noticed that to pick up translation changes, you need to:
  • Run php artisan lang:js --no-lib resources/js/translations.js
  • Restart the node watch.
    This is an annoying consequence of sharing the same translations between Laravel blade templates and front-end Vue code. You may need to add something to Task for that.

FYI: Often during development I run with APP_DEBUG set FALSE in .env because otherwise things are pretty slow - the Laravel overhead which gets all the logs through to the client.

This updates the docs to exclusively reference Task commands and removes the
alternative Docker commands. As such, we are indicating that Task is
now mandatory.

Following this, I've moved the Task experimental env variable to a dedicated
`.taskrc.yml` file. This will be more appropriate and easier to manage
then having it in the `.env.example` file.
This addresses TheRestartProject#795 (comment)

We will now use `localhost` for the default `APP_URL` in the `.env.example` file.
As such, the docs have been updated to reflect this change.
This addresses TheRestartProject#795 (comment):
- Replaces all references of "base" with "core"
- Consolidates all Docker tasks into their wildcard counterparts.
    - Instead of having a default `docker:x` task, we will now just use the
      `docker:x-*` variant to interact with the core services.
- Replaces all references of "dev" with "debug".
    - The "dev" services are in regards to phpMyAdmin and Mailhog, which
      are actually more debugging tools than services needed for "dev".
- Add profiles to the core services in the docker-compose configuration.
    - The core services will now use the core profile to keep things consistent.
      That said, we need to include the other profiles as well so other services
      can automatically start and stop the core services without us having to
      bloat the Taskfile - i.e. include multiple --profile flags.
- Update the documentation to reflect the new terminology and tasks.
This commit removes the deprecated `image: php:7.4` line from the
docker-compose configuration since we already declare the image in the Dockfile.
Ignore node_modules folder to help with issues on Windows.
@ardelato
Copy link
Contributor Author

ardelato commented Apr 14, 2025

@edwh I tested it on my Windows machine but I did not see the git error you saw. What Docker version do you have and are you using Docker Desktop or just Docker CE?

That said, I have seen this error before and applied the following patch. 4d1842c

This was needed for a Fedora machine we have that is a running an older version of Docker (v24.0.5)


As for the changes not being picked up, I found the following that could explain the underlying cause and have confirmed a solution:

Basically, Laravel's Mix, aka Webpack, is not receiving the file change events. Therefore, if we instead use Mix's polling feature, then we can pick up the changes like that.

We already have the poll script in the package.json -

"watch-poll": "mix watch -- --watch-options-poll=1000",
so if that is used instead of npm watch then the Vue changes will be picked up.

I have confirmed this worked on my Windows machine.

I forgot to update this reference in the docs when I was consolidating the
terminology for the docker commands.
@edwh
Copy link
Collaborator

edwh commented Apr 24, 2025

@edwh I tested it on my Windows machine but I did not see the git error you saw. What Docker version do you have and are you using Docker Desktop or just Docker CE?

That said, I have seen this error before and applied the following patch. 4d1842c

This was needed for a Fedora machine we have that is a running an older version of Docker (v24.0.5)

I'm running Docker Desktop 4.30.0, which is pretty recent. I tried added that change to the Dockerfile and I still see the error.

If you don't see it, then I will need to debug though I'm not sure I can see any consequences of it yet, because...

I have confirmed this worked on my Windows machine.

Me too. Can we make this the default, then?

The main issue for me now which would block use of this is speed:

  • It is very very much slower than dev against a locally hosted VM. Is that still the case for you on Windows?
  • I've seen some discussion where people recommend ignoring Docker Desktop and installing your project directly under WSL2 so that you are running the Linux Docker. I've not tried this yet.
  • I guess this would be similar to having a VM on Windows under Hyper-V, as I currently do, but using it purely to host Docker. I've not tried that yet either.
  • If it's fast on Linux and slow on Windows then that is probably something we can live with if there are these kinds of workarounds.

@edwh
Copy link
Collaborator

edwh commented Apr 24, 2025

  • I've seen some discussion where people recommend ignoring Docker Desktop and installing your project directly under WSL2 so that you are running the Linux Docker. I've not tried this yet.

@ardelato I tried this and it's much faster for me.

So rather than run the task docker:up-core from a Windows prompt, I did this:

  • used the wsl to install an Ubuntu instance get a shell
  • cd to the location of the files, e.g. /mnt/c/Users/edwar/PhpstormProjects/restarters
  • ran task docker:up-core
  • checked that if I change the files from my IDE on Windows, they get picked up

Can you see if that performs well for you? If so then we can document this as the recommended way of running on Windows.

@ardelato
Copy link
Contributor Author

Did you follow similar steps as outlined in this blog post? https://medium.com/@suyashsingh.stem/increase-docker-performance-on-windows-by-20x-6d2318256b9a

If so, then I can confirm that the Docker build speed and up speed were a lot faster. However, I came across a different issue which has to do with ownership of the mounted volumes and thus get a permission denied error when trying to run npm run watch& in the docker_run.sh script. This prevented me from validating if changed files were getting picked up.

@edwh
Copy link
Collaborator

edwh commented May 8, 2025

Did you follow similar steps as outlined in this blog post?

Yes.

I don't remember seeing a permissions error - I'll come back here next time I try it.

@edwh
Copy link
Collaborator

edwh commented May 8, 2025

Coming back to it, I remembered that I needed to do an su from within WSL. Does that help with your permissions issue?

The change to use watch-poll still needs to go in, I think. Otherwise this is looking releasable to me.

@ardelato
Copy link
Contributor Author

@edwh could you share your WSL setup and steps you've taken? I can't seem to properly get the same results you are getting.

Even after using su I still get the same permissions errors

npm ERR! code 1
npm ERR! path /var/www/node_modules/playwright
npm ERR! command failed
npm ERR! command sh -c -- node install.js
npm ERR! node:internal/process/promises:288
npm ERR!             triggerUncaughtException(err, true /* fromPromise */);
npm ERR!             ^
npm ERR! 
npm ERR! [Error: EACCES: permission denied, mkdir '/root/.cache/ms-playwright'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: '/root/.cache/ms-playwright'
npm ERR! }
npm ERR! 
npm ERR! Node.js v18.12.0

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2025-05-15T13_20_10_292Z-debug-0.log
rebuilt dependencies successfully
Created: resources/js/translations.js

   INFO  Application key set successfully.  


> watch-poll
> mix watch -- --watch-options-poll=1000

sh: 1: mix: Permission denied

ardelato added 2 commits May 15, 2025 07:07
Include a note about what the 'All' option does and a reference to the
docker-compose.yml file for more information.
There are some issues with the watch command on different operating systems.
The watch command relies on the File System Events API to detect changes in
the file system but in Windows this may be bypassed because of the multiple
layers of virtualization. Therefore a polling mechanism is more reliable.
@edwh
Copy link
Collaborator

edwh commented May 19, 2025

@ardelato

@edwh could you share your WSL setup and steps you've taken? I can't seem to properly get the same results you are getting.

This feels like something which would work better if you ping me on Slack and we do a screen share.

But:

  • I start WSL on Windows, as my usual user.
  • I do sudo su -
  • whoami then shows me as root
  • I have permissions to run mix , unlike you:

image

@edwh
Copy link
Collaborator

edwh commented Jun 2, 2025

@ardelato I think this is still with you for some final doc tweaks?

ardelato added 13 commits June 2, 2025 16:35
By utilizing the official PHP image, we can remove the need for some
PHP extensions to be installed. In addition, by removing the SSH setup,
we can remove the telnet dependency and additional sshd configuration.

From here, we can further improve the dependency installation process by
utilizing the install-php-extensions tool which will install the
dependent system packages, i.e. lib*-dev, etc, install the PHP extension,
and finally clean up after itself. Utilizing this tool we can install
the additional PHP extensions we need that are not included in the
official PHP image.

One thing to note, we will pin the install-php-extensions tool to the
current latest version for security purposes.
By default, Docker uses the root user as such
the need to specify the user in the docker-compose.yml file
and the usage of sudo in the Dockerfile are unnecessary.

We will be adding a non-root user in a later commit
to handle the file permissions of the mounted
volumes.
The working directory should be set after we've finished installing
all the dependencies and will start working with the actual app code.

In addition, we can drop the copy composer.lock and composer.json line
as they were already copied from the "." copy line.
Instead of installing composer v1 and using the phar file,
we will now just use a single instance of composer
which will be installed in the Dockerfile.
We were getting an error about the git directory not being safe for the
mounted codebase.
Introduces GID mapping between host and container to resolve file permission
conflicts when mounting volumes. The host's group ID is automatically retrieved
via Taskfile and passed as a build argument to modify the container's www-data
group. This ensures both environments share the same group permissions.

Key changes:
- Add GID build argument to Dockerfile with host group ID detection
- Configure www-data group to match host GID for consistent file access
- Set proper home directory for www-data to prevent cache pollution in mounted volumes
- Enables read/write operations on mounted files from both host and container

This resolves permission issues across different Docker environments (Docker CE,
Docker Desktop) and operating systems where virtualization and mounting behaviors
vary. In addition, it ensures tools like composer and npm do not create cache
artifacts in the project directory -- i.e. the mounted directory.
Handle the case where the GID already exists
…sions

- Introduced a new Nginx service in docker-compose.yml to serve the application.
- Updated Dockerfile to create a non-root user with customizable UID and GID for better permission handling.
- Modified docker_run.sh to use php-fpm instead of the built-in server.
- Added nginx.conf for Nginx configuration to handle PHP requests and static files.

These changes enhance the application's deployment and avoid conflicts
with the built-in www-data user and group.
The file permissions may be wrong if we mount the host directory into the container.
As such we need to chown the files on startup.

This is similar to the example Docker has documented for the Laravel project.
https://github.com/dockersamples/laravel-docker-examples/blob/main/docker/development/php-fpm/entrypoint.sh
Instead of chowning all files, let's target only the directories where
the content will change between the host and the container.
The current gitignore files are set with 0644 permissions, but we
were changing the permissions to 0755. As such, there was git diff
from this change.
@ardelato
Copy link
Contributor Author

ardelato commented Jun 2, 2025

We should be good now. I included the changes for resolving the permission issues we were seeing in Windows and updated the docs accordingly.

@ardelato
Copy link
Contributor Author

ardelato commented Jun 2, 2025

@edwh I am not really sure what to do about the Docker errors SonarCloud is mentioning. This docker image is meant to only be used locally.

@edwh
Copy link
Collaborator

edwh commented Jun 9, 2025

@edwh I am not really sure what to do about the Docker errors SonarCloud is mentioning. This docker image is meant to only be used locally.

I agree. I've marked those two as safe.

@edwh edwh closed this Jun 9, 2025
@edwh edwh reopened this Jun 9, 2025
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jun 9, 2025

@edwh edwh merged commit e29eb2c into TheRestartProject:develop Jun 16, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants