Tangible Bytes

A Web Developer’s Blog

Prettier in Docker

I’m working on a PHP project and code review brought up some formatting issues in my CSS.

I wanted to added automated formatting of these files accessible to everyone in the team without them having to install node as this isn’t a JavaScript project.

We already use Docker so that seemed an obvious choice.

At first I thought I should install node on our webserver container - but that just shows I haven’t fully made the mental leap to containers - they are not virtual machines and we should have a separate container for this task.

Also this container only needs to run when we want to run a command on it - it isn’t a sever. Once the formatting is finished it can exit and we will start a new one next time.

We already had a Dockerfile - this is just part of it showing the PHP service and the new node service (there is also a webserver and a database)

Lines 18-29 below relate to running JavaScript

 1version: "3"
 2services:
 3  #PHP Service
 4  app:
 5    build:
 6      context: .
 7      dockerfile: Dockerfile
 8    container_name: app
 9    restart: unless-stopped
10    tty: true
11    working_dir: /var/www
12    volumes:
13      - ./:/var/www
14      - ./php.ini:/usr/local/etc/php/conf.d/local.ini
15    networks:
16      - app-network
17
18  node:
19    # don't start this by default (it only runs when
20    profiles: ["nodejs"]  running a command)
21    image: node:lts-alpine3.16
22    user: node
23    container_name: node
24    tty: true
25    working_dir: /var/www
26    volumes:
27      - ./:/var/www
28    networks:
29      - app-network

I’m using a standard node alpine image - this has node 18 on a minimal linux base.

Node is installed for the user “node” uid 1000 and gid 1000

The other containers use the same uid/gid with a different name (and it’s the IDs that matter here).

I mount my files at the same place on both systems so any paths will match.

I wanted docker-compose up to only start my servers - and not this node container which is only needed when a command is run.

It seems the way to do this is profiles

If unassigned, the service is always started but if assigned, it is only started if the profile is activated.

so by default my unassigned services will come up but not my assigned one which only runs when I tell it to.

Now I can run node commands using docker-compose run

This creates a container, runs the command on it and removes the container.

It’s still quick because docker caches the images - but it doesn’t take up much resource.

docker-compose run --rm node npm -v

Checks it is running correctly

Now I can install prettier.

docker-compose run --rm node npm install --save-dev --save-exact prettier

Note that npm install runs on the container but since it installs files in a shared folder my project package.json and related files will be changed.

This together with the Docker changes mean that prettier is available to the whole team with no code install - just git pull and docker-compose (re)build.

Create an empty .prettier.json file

{}

.prettierignore

Mine looks like this

node_modules
storage/
vendor
.phpunit.result.cache
phpunit_reports/
.scannerwork/
.idea
.vscode

Now I can run and check it works

docker-compose run --rm node npx prettier -c .

and when happy it works fix all the files

docker-compose run --rm node npx prettier -w .

I found these sites informative