I'm setting up an older WordPress theme into a Docker environment, going through the process of creating a docker-compose.yml file that lets me run various services in various containers.
I've gotten very far… nginx, mysql running with php and ssl. Working.
The final piece of the puzzle is setting up a container for Node that will run Gulp to build the final theme (a gulpfile that processes all the css and js).
I've been through dozens of answers on Stack Overflow and looking at many projects on github that are similar but not the same. They've taught me a lot, I think I'm a step or two away from a deep enough understanding to grasp what I'm missing.
The Node service is mounted to a volume mapped to the local directory where gulp needs to run. npm install
builds node_modules somewhere, but not where I want, and even so, the end result is always…
internal/modules/cjs/loader.js:834
throw err;
^
Error: Cannot find module '/gulp'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:831:15)
…despite multiple attempts and mounting, working directories, COPYing and anything else that feels logical.
This is what I have so far…
docker-compose.yml
version: '3.9'
networks:
wordpress:
services:
nginx:
build:
context: .
dockerfile: nginx.dockerfile
container_name: nginx
depends_on:
- php
- mysql
ports:
- 80:80
- 443:443
volumes:
- ./wordpress:/var/www/html:delegated
networks:
- wordpress
mysql:
image: mysql:latest
command: --default-authentication-plugin=mysql_native_password
container_name: mysql
environment:
MYSQL_DATABASE: wpdb
MYSQL_USER: wpdbuser
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: secret
SERVICE_TAGS: dev
SERVICE_NAME: mysql
restart: always
tty: true
ports:
- 3306:3306
volumes:
- ./mysql:/var/lib/mysql
networks:
- wordpress
php:
build:
context: .
dockerfile: php.dockerfile
container_name: php
volumes:
- ./wordpress:/var/www/html:delegated
networks:
- wordpress
wp:
build:
context: .
dockerfile: wp.dockerfile
container_name: wp
entrypoint: ['wp', '--allow-root']
links:
- mysql:mysql
volumes:
- ./wordpress:/var/www/html:delegated
networks:
- wordpress
phpmyadmin:
build:
context: .
dockerfile: phpmyadmin.dockerfile
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin
depends_on:
- mysql
ports:
- 8081:80
- 8082:443
environment:
PMA_HOST: mysql
MYSQL_ROOT_PASSWORD: secret
restart: always
networks:
- wordpress
node:
build:
context: .
dockerfile: node.dockerfile
image: node:12.19.1-alpine3.9
container_name: nodejs
volumes_from:
- nginx
working_dir: /var/www/html/wp-content/themes/the-theme
networks:
- wordpress
Notable and I think relevant is…
- nginx service mounts a local directory that has WP inside it.
- wp service is wp-cli, not a wordpress image, instead wp is run to perform tasks such as
docker-compose run --rm wp core download
- I want to run node gulp in much the same way as wp
- the node.dockerfile is empty right now, but I'm conscious and interested in what someone else is doing with a shell script here.
Basically I'm knowledgeable enough to have a sense of where I'm messing up (with paths) but not enough to work out what to try next. Or to articulate a question.
I can show all the information I've gathered…
docker-compose run --rm node --version
…works great, result: v12.19.0
docker-compose run --rm node npm install
Success. Then…
docker-compose run --rm node gulp -v
Error: Error: Cannot find module '/var/www/html/wp-content/themes/the-theme/gulp'
Not really knowing what I'm doing, assuming the node service is mounted to the theme directory I thought I'd try:
docker-compose run --rm node node_modules/gulp -v
but that gave an error:
/usr/local/bin/docker-entrypoint.sh: exec: line 8: node_modules/gulp: Permission denied
I can confirm that a node_modules directory was indeed created where I wanted it to be when I ran npm install, and it had read from the packages.json and installed everything. I could run npm list and everything.
In case it's relevant, my project folder is…
- workspace
-- wordpress
--- wp-content
---- themes
----- the-theme
------ package.json
------ node_modules
-- docker-compose.yml
-- various-docker-files
…and it's inside that the-theme directory that I want to run gulp just like I would locally. It seems I can run npm install there, but nothing installed can be found.
I go on to attempt numerous things, such as setting the working_dir: to node_modules, or to mount none_modules.
I try things like docker-compose run --rm node ls
and I can see the insides of the_theme, some linux system directories, and node_modules.
docker-compose run --rm node ls -al node_modules
…shows me all the installed node packages.
Multiple answers elsewhere suggest rebuilding the npm install etc, no effect. And I feel I'm hampered by the fact that many of these questions and answers feature simple node.js apps where people have an untouched ready-to-go package.json they can just COPY into a simple directly structure i.e. /app in their dockerfile, where I'm dealing with a package.json that has to be read from a deeper sub directory, on a mounted local volume. Perhaps confusing me.
Additional answers suggested that it would be correct to have my node service volumes like this…
volumes:
- ./wordpress:/var/www/html:delegated
- /var/www/html/wp-content/themes/the-theme/node_modules
working_dir: /var/www/html/wp-content/themes/the-theme
But that was more of the same. Gulp not found, and a discrepancy between what was in node_modules via docker-compose run and what was on my local node_modules.
I also at various points learned that perhaps my node_modules should not even be in my theme directory as it would be locally, that they should be off in the node container – which is reasonable, but I'm not sure how to approach it, while still having access to packages.json that lives persistently in ./wordpress/wp-content/themes/the-theme and also have access to css and js that is being updated in a sub directory of that.
To summarize: I want to run
docker-compose run --rm node gulp build
on /wordpress/wp-content/themes/the-theme
and for the gulp command to do its thing, with output at
/wordpress/wp-content/themes/the-theme/dist
or similar
Update #1:
node:
build:
context: .
dockerfile: node.dockerfile
image: node:12.19.1-alpine3.9
container_name: nodejs
depends_on:
- nginx
ports:
- 3001:3000
tty: true
volumes:
- ./wordpress:/var/www/html:delegated
- /var/www/html/wp-content/themes/inti-acf-starter/node_modules
working_dir: /var/www/html/wp-content/themes/inti-acf-starter
networks:
- wordpress
I've added tty: true so that I can -it into the node container and poke around.
This drops me in my working_dir. I can npm install
here. I can see a node_modules directory. I cd into it and it's full. I try to run any of these I get:
sh: gulp: not found
OK. So npm install --global
I guess.
This doesn't install everything in my package.json, and what is installed and appearing in node_modules under /var/www/html/wp-content/themes/the-theme
…is not reflected locally in ./wordpress/wp-content/themes/the-theme/node_modules
I feel I should remove that second volume and just use the locally mapped one. But I'm not sure what to do about the rest. Installing just gulp globally means I can run just that inside the container with -it, but the gulpfile full of requires now can't find any.
Update #2:
node:
build:
context: .
dockerfile: node.dockerfile
image: node:12.19.1-alpine3.9
container_name: nodejs
depends_on:
- nginx
ports:
- 3001:3000
tty: true
volumes:
- ./wordpress:/var/www/html:delegated
- /var/www/html/wp-content/themes/the-theme/node_modules
working_dir: /var/www/html/wp-content/themes/the-theme
networks:
- wordpress
I understand now that each npm install
that node is actually dropping everything into:
/usr/local/lib/node_modules/inti-acf-starter/node_modules
With npm install -g gulp-cli@2.1.0
first I can now run Gulp!
My project compiles correctly. Well most of it. I have to keep the node service tty, and run npm and gulp inside of that only.
Running things like:
docker-compose run --rm node gulp build
…can't find gulp.