felixarntz / wordpressdev

WordPress core development environment based on Lando.
GNU General Public License v2.0
13 stars 0 forks source link

Create a separate Node service #2

Closed ataylorme closed 5 years ago

ataylorme commented 5 years ago

Rather than adding Node to the existing appserver service a new service for node should be used. One of the advantages of Docker is being able to use containers focused on one task.

Lando does this out of the box with different services for PHP, the database, Redis, etc.

See the setting up additional services doc and my .lando.yml for an example

westonruter commented 5 years ago

I could be wrong, but I think Node needs to be installed in appserver in addition to another container. Node needs to be in the appserver container for running Grunt. This is separate from Node that is used to actually run a server which would indeed be in another container.

felixarntz commented 5 years ago

@ataylorme I did what you said initially, and just couldn't get it to work for the reasons @westonruter outlined.

Maybe I did something wrong while doing that, but connecting the separate Node service so that I can call npm and grunt from appserver when SSHd in via lando ssh just didn't work.

westonruter commented 5 years ago

@ataylorme or would that be best done by letting the Node service have access to the same filesystem as the appserver? I don't know if that's even possible.

ataylorme commented 5 years ago

@westonruter yes, any new services you add to Lando will have access to the file system. My recommendation would be a Node service using a Dockerfile that has Node and Grunt installed. See my snippet in #1 for how I do that. My example is gulp but Grunt should be an easy switch.

If you wanted to run an express server or some other backend Node process you could use the same service or have separate ones. I prefer to separate services and their tasks by language (JS, PHP, etc.) but it comes down to preference. I prefer multiple, smaller services that do a few things well to one monolithic service.

Commands can be mapped to services with the tooling declaration. So if you had a service named node then the snippet below would allow you to run lando grunt which would run the command grunt inside the node service container. It will be run relative to the current local directory, so you could run it from the project root, a plugin, theme, etc.

tooling:
  grunt:
    service: node

Similarly, you can run bash scripts (or anything really) with Lando commands. Below is my example that calls a bash script that will find gulp files throughout the project and run npm install and gulp in their directory with lando gulp-build. I like this as I can run the same scripts/processes locally that I use in CI services.

tooling:
  gulp-build:
    description: Install npm dependencies and run gulp
    cmd: ./.circleci/build-gulp-assets.sh
    service: node
westonruter commented 5 years ago

I prefer to separate services and their tasks by language (JS, PHP, etc.) but it comes down to preference. I prefer multiple, smaller services that do a few things well to one monolithic service.

Here's a complication that maybe you have some advice for. The Grunt command to build the AMP plugin depends on Node, obviously, but it also needs to invoke WP-CLI:

https://github.com/ampproject/amp-wp/blob/9958f6fcae2b1fb39ae3f35e90df6a91de8026b5/Gruntfile.js#L41

Would this not require that Node and WP-CLI be installed on the same service?

ataylorme commented 5 years ago

Would this not require that Node and WP-CLI be installed on the same service?

Yes, unless you split the Grunt command up and ran the Node parts in a Node service and the wp-cli parts in appserver.

Again, these decisions are just preference. I don't think the advantages of using separate services outweighs the hassle it would take to modify/modularize your Grunt build process.

The Lando Slack instance is a great place to have a discussion like this to get multiple opinions.

felixarntz commented 5 years ago

To clarify, when you use a separate node service, you can do lando npm, but not lando ssh and then npm right?

westonruter commented 5 years ago

You could still do lando ssh node to SSH into the Node container. In that container npm would be available.

felixarntz commented 5 years ago

Ah okay, I didn't know that. It still feels odd to me that you can't lando ssh in and then do grunt and phpunit from the same session. Maybe that's just me not having used lando ... commands before though.

ataylorme commented 5 years ago

I didn't know that. It still feels odd to me that you can't lando ssh in and then do grunt and phpunit from the same session.

Two thoughts on this

1) You should not ssh into each service to run commands. SSH is really for debugging. You should use be using the tooling feature to create Lando commands that run what you need in the container. For example, lando grunt could run grunt. See this doc on how to set that up

2) You can do that if the service (container) has all the requirements, in this case PHP and Node. When using Docker though it is best (in my opinion) to create separate services/containers rather than having a monolithic container that does all the things. If you have that set up then there is really not much difference from a VM solution like VVV. The advantage containers have is being able to have them be more lightweight and set up to do one job and so efficiently.

westonruter commented 5 years ago
  1. When using Docker though it is best (in my opinion) to create separate services/containers rather than having a monolithic container that does all the things.

Yeah, that makes sense. However, both Node and PHP need to be in the same container here for WP-CLI and Node to be able to call each other.

ataylorme commented 5 years ago

I'm not sure if you can call one service from another. I asked in the Lando Slack for you though.

ataylorme commented 5 years ago

The answer is in. In rc.1+ you can set up tooling commands that call multiple services

mycommand:
  # Run our two build steps
  cmd:
    - service1: command1
    - service2: command2

So you can probably split the shell commands in the AMP Grunt process in this way.

build_amp:
  # Run our two build steps
  cmd:
    # Readme
    - appserver: ./dev-lib/generate-markdown-readme
    # PHP Unit
    - appserver: phpunit
    # Verify matching version
    - appserver: php bin/verify-version-consistency.php
    # Webpack production
    - node: cross-env BABEL_ENV=production webpack
    # pot to PHP part 1
    - node: npm run pot-to-php
    # pot to PHP part 1
    - appserver: php -l languages/amp-translations.php
    # makepot
    - appserver: wp i18n make-pot . languages/amp-js.pot --include="*.js" --file-comment="*/null/*"
    # Create build .zip
    - appserver: if [ ! -e build ]; then echo "Run grunt build first."; exit 1; fi; if [ -e amp.zip ]; then rm amp.zip; fi; cd build; zip -r ../amp.zip .; cd ..; echo; echo "ZIP of build: $(pwd)/amp.zip"
westonruter commented 5 years ago

@ataylorme thanks, but this will require the general Lando environment to have a command specifically for the AMP plugin. In other words, we wouldn't be able to package a build command in the AMP plugin for use in an arbitrary environment if php and node aren't available on the same container. It seems the only way to achieve that would be to allow two containers to invoke commands on each other, but this does not seem feasible according to a subsequent reply in Slack:

having service1 be able to invoke some command in service2 is definitely a much more tricky endeavor so tricky that i dont think we intend to ever support something like that

So I don't think having separate services is practical, even though it is surely more pure.

ataylorme commented 5 years ago

So I don't think having separate services is practical, even though it is surely more pure.

I agree for this use case. Closing this out. We cam work on a Dockerfile that supports Node and PHP in #1