Dockerize Local Bedrock & Sage Development with Lando

Hey Gwyn,

Sure thing. Most of the original guide is still valid. But, here are the rough steps/files you need. This is assuming you are using the latest version of Bedrock and Sage 10 (not 9).

INSTRUCTIONS FOR LANDO, BEDROCK, AND SAGE 10

  1. Pre-requisites: Install Docker and Lando.

  2. Create a bedrock project using composer (on host machine) or cloning the project directly from Github: https://github.com/roots/bedrock

  3. Add the following .lando.yml file within your bedrock project, subbing out the ‘name’ (example-name) and local dev URL (example.local).

    name: example-name
    recipe: wordpress
    env_file:
      - .env
    proxy:
      appserver_nginx:
        - example.local
      theme:
        - localhost:3000
    config:
      php: 7.4
      composer_version: 2-latest
      via: nginx
      webroot: web
      database: mariadb
      xdebug: true
    
    # Add the following if you plan to use Sage as a starter theme
    services:
      theme:
        type: node:14 # MUST BE >12 TO WORK WITH SAGE 10
        overrides:
          ports:
            - 3000:3000
    
    # TODO Work on build steps w/ Lando and tooling here...
    tooling:
      yarn:
        service: theme
    
    excludes:
      - vendor
      - node_modules
    
  4. Add a .env file to the root of the project. The Bedrock project on Github gives an example. HOWEVER, if you are using Lando, you MUST use the following values for DB_NAME, DB_USER, DB_PASSWORD, DB_HOST. (i.e. You cannot change the database name–these are hard-coded into the WordPress ‘recipe’ that Lando uses behind the scenes.)

    Be sure to change WP_HOME to be your local dev testing URL (i.e. not http://example.local). This should be similar to what you put in the .lando.yml file under the proxy settings for appserver_nginx.

    #.env 
    
    DB_NAME='wordpress'
    DB_USER='wordpress'
    DB_PASSWORD='wordpress'
    DB_HOST='database'
    
    # Optionally, you can use a data source name (DSN)
    # When using a DSN, you can remove the DB_NAME, DB_USER, DB_PASSWORD, and DB_HOST variables
    # DATABASE_URL='mysql://database_user:database_password@database_host:database_port/database_name'
    
    # Optional variables
    # DB_HOST='localhost'
    # DB_PREFIX='wp_'
    
    WP_ENV='development'
    WP_HOME='http://example.local'
    WP_SITEURL="${WP_HOME}/wp"
    WP_DEBUG_LOG=/path/to/debug.log
    
    # Generate your keys here: https://roots.io/salts.html
    AUTH_KEY='EDwF^3V)<XG|{U:MpP]]4m4>8*@OMjks!ZO+NK)e}|4rG?+o=qt|K/Yk.R`6qVTl'
    SECURE_AUTH_KEY='O}N<lrE:$tgV+ppq0FM@Kguv7z-I`uS{wX9Nkd8p9X[[ck^PczlBoQi[HW!m<4!#'
    LOGGED_IN_KEY='1KhBZncviq4[&B1Jj/X%CJ_7{U2GpFa8`LJg0FtcH>0J>.,Uxvi_1u[I/M+}m.<T'
    NONCE_KEY='q$C)T+x[(]s4phDED.0:j=TBS9S9T}P6V#`d3UW7};8!=.b]a}|s3$Gi[;iim`j>'
    AUTH_SALT='w$N]UDvvF:BaX][c`1|q7fQiPRn>zX$rW.|[reJ:47MOe_*gP]/?}w7,6$o[9f$*'
    SECURE_AUTH_SALT='KMN$qXOzI`Z!*,brAFFC?YG*7uj+qAR*=gQ8L?E/H);E6V1Wdu4?$0Y?3%}:`oG<'
    LOGGED_IN_SALT='>bXCZ!FRv;$Os!a1Keig|{H$x@^zPx[O$[yvumM2M$!yb]`C(iJf0%x|:Gm=q3I,'
    NONCE_SALT=',Z=i:BGogtOTjg^]H7,u=`5?gKMts+.-c.4!+P2@==*U6{)M1u#4o)nrP%H7C5*0'
    
  5. Edit your hosts file on your OS to add the local dev URL. If you are on Linux, edit /etc/hosts as the root user. Add the following line:

    127.0.0.1 example.local
    

    This will allow the local testing URL to work properly when you go to visit it later in a web browser.

  6. Run lando start. This will start setting up the Docker containers that Lando uses behind the scenes for our local environment.

  7. Run lando composer install and lando composer update in the project. This set will install WordPress and the PHP dependencies that Bedrock uses to run properly.

  8. Go to the web/app/themes folder in the project.

  9. Clone Sage v10 from Github (https://github.com/roots/sage). Alternatively, use you may use lando composer require roots/sage:dev-master to install Sage using Composer instead. NOTE: If you are using Composer, you MUST use the ‘dev-master’ version to get Sage v10. These steps will not work for Sage v9.

  10. Now, go into the new theme folder we created in the previous step named sage/.

  11. Edit the webpack.mix.js file in the Sage theme folder. You want to change the .browserSync URL. See an example of this file below:

    const mix = require('laravel-mix');
    require('@tinypixelco/laravel-mix-wp-blocks');
    
    /*
    |--------------------------------------------------------------------------
    | Mix Asset Management
    |--------------------------------------------------------------------------
    |
    | Mix provides a clean, fluent API for defining some Webpack build steps
    | for your Sage application. By default, we are compiling the Sass file
    | for your application, as well as bundling up your JS files.
    |
    */
    
    mix
    .setPublicPath('./public') 
    .browserSync('example.local'); // <-- CHANGE RIGHT HERE TO WHATEVER LOCAL DEV URL YOU CHOSE
    
    mix
    .sass('resources/styles/app.scss', 'styles')
    .sass('resources/styles/editor.scss', 'styles')
    .options({
        processCssUrls: false,
    });
    
    mix
    .js('resources/scripts/app.js', 'scripts')
    .js('resources/scripts/customizer.js', 'scripts')
    .blocks('resources/scripts/editor.js', 'scripts')
    .autoload({ jquery: ['$', 'window.jQuery'] })
    .extract();
    
    mix
    .copyDirectory('resources/images', 'public/images')
    .copyDirectory('resources/fonts', 'public/fonts');
    
    mix
    .sourceMaps()
    .version();
    
    
  12. Run lando yarn and lando yarn build. This will install the Node dependencies for the Sage theme to work.

  13. This step is kinda optional, but install the PHP dependencies for Sage v10. Run lando composer install and lando composer update IN THE SAGE THEME FOLDER. NOTE: This is different than before in Step #7 when we installed PHP dependencies for Bedrock.

  14. If you got this far, we are now ready for development: we have Lando, Bedrock, and Sage properly installed now. You can now visit http://example.local in your web browser. You should see the ‘default’ WordPress installation wizard. Proceed through the wizard as you would normally. Don’t see the WP wizard? Check to make sure that you don’t have other services like Apache running on your host machine. We don’t want other programs messing with how Lando is serving up websites. If you are on Ubuntu based distributions, run sudo systemctl stop apache2 in your terminal to stop the Apache process. Still don’t see the WP wizard? Check to make sure you do not have other Node apps running on your PC trying to serve up a website on localhost port 80 (as this is what we are doing with Lando right now).

  15. You can now see your Bedrock/Sage website at http://example.local. HOWEVER, if you want to set up hot-reloading in your browser, open another terminal on your computer. Visit the theme folder of your Bedrock project: web/app/themes/sage. Run lando yarn start in this folder. This will set up hot-reloading. Keep this terminal window open throughout your development process. EXTREMELY IMPORTANT NOTE: Your site will only hot-reload at http://localhost:3000–NOT http://example.local (if you followed my steps). So, be sure to do your theme development at http://localhost:3000/ in your browser. http://example.local will just show your WordPress site without the hot-reloading.

6 Likes

@Gwyn_Hockridge

I left you (and the world) some detailed instructions above. If you are still having issues, please do not hesitate to reach out to me. We could chat together to get this working for you. :slight_smile:

3 Likes

@coltoneakins
Thanks so much! Will check it out this morning. Do you know if this config will work with sage 9? Doubt we’ll be able to use Sage 10 in production until it’s out of dev (and ideally working with tailwind).

Hey Gwyn,

Most of the original tutorial by Roots still applies for Sage 9. However, the biggest change is probably the Lando config file for Lando v3–some of the directive names changed. For example, the ‘nginx’ directive changed to ‘appserver_nginx’.

Here is my most recent, working configuration for Sage 9 from an old project:

name: example-name
recipe: wordpress
env_file:
  - .env
proxy:                
  appserver_nginx:              # Optional: if you exclude this, Lando will serve it as name.lndo.site
    - example.local
  theme:              # Optional: add this if you include the Sage specific config down below
    - localhost:3000
config:
  php: '7.3'
  via: nginx
  webroot: web
  database: mariadb
  xdebug: true

# Add the following if you plan to use Sage as a starter theme
services:
  theme:
    type: node
    services:
      ports:
        - 3000:3000

# TODO Work on build steps w/ Lando and tooling here...
tooling:
  build:
    description: Manually invokes all our build steps
    cmd:
      - appserver_nginx: composer install
      - theme: composer install
      - theme: yarn install
  yarn:
    service: theme

As you can see, it is pretty similar to the original tutorial. If you have have trouble getting hot-reloading to work, just make sure you are running lando yarn start in the Sage theme folder of your WP installation.

Also, make sure no other services such as Apache or other Node apps are running on port numbers that Lando is also using.

1 Like

ABOUT USING BROWSERSYNC FOR HOT RELOADING + THE BROWSERSYNC UI:

NOTE: In my original reply, I forgot to also expose port 3001 (the default port used by Browsersync for its ‘UI’ panel). If you want hot reloading AND the Browsersync UI dashboard, use the following .lando.yml file:

name: example-name
recipe: wordpress
env_file:
  - .env
proxy:
  appserver_nginx:
    - example.local
  theme:
    - localhost:3000
    - localhost:3001
config:
  php: 7.4
  composer_version: 2-latest
  via: nginx
  webroot: web
  database: mariadb
  xdebug: true

# Add the following if you plan to use Sage as a starter theme
services:
  theme:
    type: node:14 # MUST BE >12 TO WORK WITH SAGE 10
    overrides:
      ports:
        - 3000:3000
        - 3001:3001 

# TODO Work on build steps w/ Lando and tooling here...
tooling:
  yarn:
    service: theme

excludes:
  - vendor
  - node_modules

BE SURE TO RUN lando rebuild AFTER MAKING CHANGES TO THIS FILE. THIS IS NOT OPTIONAL.

Lastly, please note that the ‘external URL’ feature of Browsersync will not work by default in Lando for security reasons. This is the feature that allows you to connect to your development site on your local LAN–such as using your cell phone to browse your dev site for testing purposes.

This is because Lando uses Docker behind the scenes; it is insecure to expose your app on your local LAN because other devices on your local network could essentially steal data from your app.

However, if you want to get Browsersync to work 100% (hot-reloading, the UI dashboard, AND the ‘external url’ feature working), you have to change the bindAddress to expose your services (a.k.a. Docker) on the LAN. THIS IS NOT ENABLED BY DEFAULT FOR SECURITY. See instructions here: https://docs.lando.dev/guides/access-by-other-devices.html#lando-share-testing-over-the-internet

Once you make these changes, you will likely have to run lando rebuild to rebuild Lando (Lando is not like docker-compose, most changes made to the .lando.yml file REQUIRE a rebuild). Also, you may have to edit the webpack.mix.js file to add more options to Browsersync to adjust the proxy URL and/or host. See the Browsersync documentation: https://browsersync.io/docs/options

3 Likes

Thanks to @coltoneakins, I was finally able to run Lando version 3.1.4 and Browsersync on a mobile device too.

If you want to try, use the following:

vim ~/.lando/config.yml

[config.yml]

# https://docs.lando.dev/config/security.html#exposure
# Bind my exposes services to all intefaces
bindAddress: 0.0.0.0

[.lando.yml]

name: myappname
recipe: wordpress
env_file:
  - .env
config:
  php: '7.4'
  via: nginx
  database: mariadb
  xdebug: false
  webroot: web
  composer_version: 2-latest
proxy:
  mailhog:
    - mailhog.lndo.site
services:
  database:
    type: mariadb
    portforward: 3306
    creds:
      user: myuser
      password: mypassword
      database: mydbname
  mailhog:
    type: mailhog
    hogfrom:
      - appserver
    portforward: true #1026
  node:
    type: node:14
    globals:
      node-sass: "latest"
    overrides:
      ports:
        - 3000:3000
        - 3001:3001
tooling:
  npm:
    service: node
  node:
    service: node
excludes:
  - vendor
  - node_modules

[webpack.mix.js]

mix.browserSync({
    https: true,
    host: 'localhost',
    ui: {
        port: 3001
    },
    injectChanges: true,
    notify: false,
    proxy: 'https://myappname.lndo.site',
    port: 3000,
    open: false
});

You should now be able to looking for your own IP address (example 192.168.1.100) and - on your mobile devices in the LAN - visit the https://192.168.1.100:3000 URL

Hope it helps.

1 Like

went smoothly up to step 14, 502 bad gateway

edit: did a lot of digging now just getting 404 not found http://example.local

1 Like

@Jack_Kudla

Hi Jack,

I’d like to help you out more with this–but, I need more details from you.

Getting a 404 error might mean either of the following:

  1. A service like Apache may be running on your computer which is interfering with Lando.
  2. There is a permissions issue with the WordPress file your are trying to visit in your web browser. For example, if you are visiting the home page, the index.php file may have bad permissions.
  3. (More unlikely) Your computer may have had problems binding the example.local URL to your computer’s localhost.

I would try @Davide_Prevosto’s steps above. It may fix your issue.

Otherwise, if you feel comfortable doing so, maybe we could screenshare via Discord and troubleshoot this together?


Note: This issue is probably an issue with YOUR computer/setup–not the steps above. This is because other people tried my steps and verified they are working.

If you want to use an external MySQL tool like Sequel Ace, change the .lando.yml like this.

  1. remove the database directive from config.

  2. add the following under services

services:
  database:
    type: mariadb:10.6
    portforward: 33061   # port for external app access

I am tying to recover an older Bedrock project (1.10.2). I followed the recommended lando.yml setup.

name: marmalade
recipe: wordpress
env_file:
  - .env
proxy:
  appserver_nginx:
    - marmalade.lndo.site
  theme:
    - localhost:3000
config:
  composer_version: 2-latest
  php: '7.2'
  via: nginx
  webroot: web
  database: mariadb
  xdebug: true
services:
  theme:
    type: node:10.15.0
    overrides:
        ports:
          - 3000:3000
  ruby:
    type: ruby:2.4
    install_dependencies_as_me:
      - gem install capistrano
      - gem install capistrano-composer
      - gem install capistrano-wpcli
      - gem install bedrock-capistrano-uploads
      - gem install capistrano-file-permissions
tooling:
  yarn:
    service: theme
  gem:
    service: ruby
  ruby:
    service: ruby
  sshKey:
    service: ruby
    cmd:
      - cat /etc/ssh/ssh_config
  database:
    portforward: 3306

.ENV

DB_NAME=wordpress
DB_USER=wordpress
DB_PASSWORD=wordpress

# Optional variables
DB_HOST=localhost
DB_PREFIX=msbi_

WP_ENV=development
WP_HOME=http://test.lndo.site
WP_SITEURL=${WP_HOME}/wp

It seems the autoloader does not work correctly. I am keep getting an error on wordpress installation.

Warning: mysqli_real_connect(): (HY000/2002): No such file or directory in /app/web/wp/wp-includes/wp-db.php on line 1626

No such file or directory

Error establishing a database connection

This either means that the username and password information in your wp-config.php file is incorrect or we can’t contact the database server at localhost. This could mean your host’s database server is down.

  • Are you sure you have the correct username and password?
  • Are you sure you have typed the correct hostname?
  • Are you sure the database server is running?

If you’re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the WordPress Support Forums.

Any idea why?

Cheers
Olaf

Now that Sage 10 officially rolled out - any suggestions on updating lando config?

One that’s probably worth noting:

+1 !
If someone can shere his lando config + bud config that would be wonderful !

So I spent a lot of time and reading trying to get this setup to work and I feel I am pretty close. But somehow I can’t get browsersync/localhost to work.

The problem:
After lando start the following url is red:
THEME URLS http://localhost

lando yarn dev seems to work fine, no errors and it notices changes I make etc.
But http:/localhost:3000 is not accessible (‘This site can’t be reached’)

Any help would be greatly appreciated!

My configuration:

.lando.yml

name: bedrock
recipe: wordpress
env_file:
  - .env
proxy:
  appserver_nginx:
    - bedrock.lndo.site 
  theme:
    - localhost:3000
    - localhost:3001
config:
  php: 7.4
  composer_version: 2-latest
  via: nginx
  webroot: web
  database: mariadb
  xdebug: true

# Add the following if you plan to use Sage as a starter theme
services:
  theme:
    type: node:16
    overrides:
      ports:
        - 3000:3000
        - 3001:3001

tooling:
  yarn:
    service: theme

excludes:
  - vendor
  - node_modules

.env

DB_NAME='wordpress'
DB_USER='wordpress'
DB_PASSWORD='wordpress'
DB_HOST='database'

WP_ENV='development'
WP_HOME='https://bedrock.lndo.site'
WP_SITEURL="${WP_HOME}/wp"

# Generate your keys here: https://roots.io/salts.html
# (I tried without salts but didn't make a difference, so I probably put them back here)

bud.config,js (identical to the latest Sage)

/**
 * @typedef {import('@roots/bud').Bud} bud
 *
 * @param {bud} app
 */
module.exports = async (app) => {
  app
    .entry({
      app: ['@scripts/app', '@styles/app'],
      editor: ['@scripts/editor', '@styles/editor'],
    })

    .assets('images')

    .watch('resources/views/**/*', 'app/**/*')

    .proxy('http://bedrock.lndo.site')

    .serve('http://localhost:3000');
};

I’ve also been fighting with this issue. I had a working lando + bedrock + sage config (basically the same as @cim posted above) that worked well while using mix and with bud 5.3.0. Once I updated to bud 5.5.0 I could not get bud dev to work properly.

When I use bud.serve(‘http://localhost:3000’) it runs but I get no response from localhost:3000 and the ‘[dev]’ and ‘[proxy]’ urls in the terminal show as grey. When I use bud.serve(‘http://bedrock.lndo.site:3000’) i get the error:

Error: listen EADDRNOTAVAIL: address not available 172.19.0.5:3000

If I remove bud.serve(), it succeeds using a random port which I also can’t access.

Yep same problem for me inside my own docker image for compiling assets.

Some more info…
Reverting to bud 5.4.0 lets me load http://localhost:3000 and http://bedrock.lndo.site:3000, but hot reloading is broken. I get a CORS error

Access to fetch at 'http://bedrock.lndo.site/app/themes/sage/public/app.afb458e755e818e47fec.hot-update.json' from origin 'http://bedrock.lndo.site:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I can confirm that reverting back to Sage 10 beta 3 (with bud 5.3.2) fixes hot reloading for me.

Maybe this bug in bud has something to do with it?

I’m using Lando (Docker wrapper) and I have exposed the port 3000 for node. But if I remove the .serve() line, i cant use the generated localhost:xxxx as this port hasn’t been exposed in docker and site using localhost:xxxx is unreachable.

If i instead use

.serve('http://localhost:3000');

and run lando yarn dev, the site is still unreachable at http://localhost:3000’;

I can however always reach the site at the domain ie http://example.test/

So my understanding is since I am using Docker, I have to remove the serve() line, but I also need to find a way to expose any random generated port on localhost through docker?

I’ve been trying to troubleshoot this all week. I’m not sure if it’s a Bud issue or Lando. My lando file looks like this, but I’ve also tried a separate sub domain for the theme proxy, with and without a specific port.

proxy:
  appserver:
    - sage.lndo.site
  theme:
    - localhost:3000
config:
  php: '7.4'
  composer_version: 2-latest
  webroot: web
services:
  theme:
    type: node:16
    overrides:
      ports:
        - 3000

When i visit http://localhost:3000 directly or curl -I 'http://localhost:3000 i get ’ Empty reply from server’, but if I lando ssh -s theme and then run the same curl command, I get the expected response:

HTTP/1.1 200 OK
content-type: text/html; charset=UTF-8
date: Thu, 17 Mar 2022 16:09:15 GMT
link: <https://sage.lndo.site/wp-json/>; rel="https://api.w.org/", <https://sage.lndo.site/wp-json/wp/v2/pages/23>; rel="alternate"; type="application/json", <https://sage.lndo.site/>; rel=shortlink
server: Apache/2.4.52 (Debian)
x-powered-by: PHP/7.4.28
connection: close
x-proxy-by: @roots/bud
x-bud-proxy-origin: https://sage.lndo.site
x-bud-dev-origin: http://localhost:3000
content-length: 0

It seems, for some reason, that requests are being properly directed to the theme container, or are somehow being modified, but I can’t track down why.

Also, when i specify the same domain in bud.serve as in proxy, i get the error Error: listen EADDRNOTAVAIL: address not available 172.19.0.2:3000

@noahott Yeah I have the exact same issue. I also installed a fresh Sage 10.1.2 just released a few hours ago, still same issue.