Lando services are our distillation of Docker containers into their most important options combined with some special sauce to setup good networking, certificates and SSH keys as well as options to run build steps and provide low level overrides.
You can use the top-level
services config in your Landofile to define and configure a service. The various options you can specify in any service regardless of the service type are shown below:
services: myservice: app_mount: delegated type: some-service:with-optional-version overrides: build: build_as_root: run: run_as_root: moreHttpPorts:  scanner: true
myservice in the example above can actually be set to anything the user wants but common conventions are things like
Each service also contains a bunch of its own configuration options. As such, we highly recommend you check out the documentation for each service. For example, some of the configuration options available to the
php service are shown below:
service: appserver: type: php:7.2 webroot: web xdebug: true composer: phpunit/phpunit: "*" config: php: config/php.ini
Docker compose files are loaded first!
If you want to load Docker compose files and use services, you should note that compose files are loaded first. This means that depending on how you name things, your services could override things set in your compose files.
The following services are currently supported. Please check out each one to learn how to use them.
One of the great features of Lando is its ability to destroy a single planet... we mean add additional dependencies or build steps to your service without the hassle of having to build or manage your own Dockerfiles.
Note that build steps will ONLY RUN THE FIRST TIME YOU SPIN UP YOUR APP. That means if you change them, you will need to run
lando rebuild for them to re-run.
When should I use build steps?
If you need additional on-server dependencies like php extensions or node modules, it sounds like a build step may be for you. If you have automation, you want to run EVERY TIME and you may want to consider using events instead.
There are four major build steps.
buildruns as "you" and before your service boots up
rootand before your service boots up
runruns as "you" and after your service boots up
rootand after your service boots up
An example to consider is shown below:
services: appserver: type: php:7.1 build_as_root: - apt-get update -y && apt-get install -y libmemcached-dev - pecl install memcached - docker-php-ext-enable memcached run: - composer install node: type: node:10 build: - yarn run: - /helpers/some-helper-script.sh run_as_root: - echo "127.0.0.1 mysite.lndo.site" >> /etc/hosts
As you can likely surmise from the above, each step is intended for a pretty specific use case:
buildto install application dependencies that are needed before you start your application
build_as_rootto install low level server packages required by your application
runto install application dependencies or run build steps that require your application be started first
run_as_rootfor any other post-start
rootlevel one-time setup commands.
Of course, these steps must make sense within the context of the container you are running them in. For example, you will not be able to run
dnf inside of a
debian flavored container. Also note that the default working directory that the commands run in inside the container is
Another potential consideration is "dependent commands". Each line of a build step runs in a separate subshell; so if COMMAND B is dependent on something provided by COMMAND A such as
sourcing a file, you should combine the commands with
&& and put them on a single line.
Using SCRIPTY things
While the following example can work, please note that it is NOT SUPPORTED.
run: - | /bin/sh -c " if [ ! -z $LANDO_MOUNT ]; then do something some other command fi "
In these situations, it is highly recommended you create a script and reference that instead. This keeps things cleaner and more portable.
#!/bin/sh if [ ! -z $LANDO_MOUNT ]; then do something some other command fi
run: - /app/my-script.sh
An exception to this rule is the "one-liner" which may be favorable to a separate script. Note that you will need to wrap the command in the correct
shell for it work correctly. Also,
~ will resolve only if you wrap it in bash.
Will not work
run: - if [ ! -z $LANDO_MOUNT ]; then do-stuff; fi
build: - mkdir -p ~/.drush/site-aliases
run: - /bin/sh -c "if [ ! -z $LANDO_MOUNT ]; then do-stuff; fi"
build: - /bin/sh -c "mkdir -p ~/.drush/site-aliases"
ENTERING THE DANGER ZONE
While the below options can be very powerful in the hands of a seasoned pro, they are not for the faint of heart. Please be careful and note that YMMV.
While we will make a good faith effort to support intrepid users, please note that once you go down any of these paths you are more or less on your own!
Lando services are just an abstraction layer on top of the Docker compose v3 file format. What this means is that behind the scenes your Landofile is being translated into a SHLOAD of SUPERNASTY looking
docker-compose files which are then being used to power your app.
We give you access to the Docker Compose layer with the
You can only override Docker Compose's top-level `services` config
Overrides you specify get merged and injected directly into the
services config used by Docker Compose. This means that you cannot use overrides to alter top level
volumes. If you are looking for that kind of POWER, we suggest you look at the custom service.
Here is an example of an overridden
apache service that uses a custom image and injects some additional environment variables. However, you can put anything into
overrides that you can put into the
services config of a Docker Compose file. Note that if you change the image, your success in running with that image is directly correlated to how close that image is to the ones we use by default. For that reason, it is highly recommended your custom images are extended from ours so your chance of doing this with great success is maximized.
If you are looking to use a completely different image then we recommend you use a custom compose service.
services: html: type: apache:custom overrides: environment: STUFF: THINGS THINGS: GUYS image: pirog/myapache:2 volumes: - ./mythings:/tmp/mythings
Lando will automatically mount your codebase in every container at
/app using the
:delegated performance optimization flag. However, you can change the mount flag on a per-service basis or disable the mount entirely if you so choose.
Do not mount my application code
app_mount to either
services: my-service: type: apache app_mount: false my-service2: type: nginx app_mount: disabled
Mount with a different flag
app_mount to any valid Docker bind mount third field.
services: my-service: type: apache app_mount: ro my-service2: type: nginx app_mount: cached
Lando will attempt to assign
localhost addresses to any service that has ports
443 exposed. By default, this is most of our services. An exception is the
compose service which requires the user manually expose the ports they need at the Docker Compose level. You can tell Lando to assign
localhost addresses to additional
http ports with the following.
services: myservice: type: apache moreHttpPorts: - '8888' overrides: ports: - '8888'
Note that while you can do the above, it is highly unlikely you will need to do it as most Lando services provide automatic handling of this. Also note the use of the service overrides to ensure that port
8888 is actually exposed.
Service URL Scanning
Lando will automatically try to scan all
proxy URLS after your app starts. We do this to:
- Provide some immediate feedback to the user regarding the health of their application and the routing that Lando has set up for it
- Help compile first-run application caches behind the scenes to improve initial loaded-in-browser speed
Note that by default, the "scan" will pass unless your app returns either a
404 https status code. The results of the scan will be coded:
- GREEN - Scan passed and you are good to go!
- YELLOW - Scan was not attempted
- RED - There may be a problem with your networking, routing or application
That said, we do realize there are legitimate use cases where you may not want this behavior or have purposefully set up your application to emit one of the naughty status codes above. For these use cases, you can disable the scanner as shown below:
services: myservice: type: apache scanner: false
If you find that your build steps are approaching Moby Dick length, you can use overrides to build directly from a Dockerfile instead. This can keep your Landofile tidy and has the added benefit of your service being shippable like any Dockerfile.
An example that extends our base
php image to add another extension is shown below:
build is going to be relative to your app root.
services: appserver: type: php:custom overrides: build: ./php image: pirog/php:7.1-fpm-custom
This lives inside of the
./php directory referenced in the
FROM devwithlando/php:7.1-fpm RUN apt-get update -y \ && docker-php-ext-install pcntl
Building a Custom Service
If the above is not enough and you still crave more power, you can consider our "catch all" custom service. This allows power users to specify custom services that are not currently one of Lando's "supported" services.
Technically speaking, this service is just a way for a user to define a service directly using the Docker Compose V3 file format and still get some of the Lando secret sauce.
THIS MEANS THAT IT IS UP TO THE USER TO DEFINE A SERVICE CORRECTLY.
This service is useful if you are:
- Thinking about contributing your own custom Lando service and just want to prototype something
- Using Docker Compose config from other projects
- Need a service not currently provided by Lando itself
You will need to rebuild your app with
lando rebuild to apply the changes to this file. You can check out the full code for this example over here.