Lando Service
The lando service is the lowest level api: 3 service available in Lando.
Generally you will want to use a more specific service like type: php but this service can be good 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
It implements a super-set of the Docker Compose Version 3 Spec and usually requires some slight tweaks of existing Docker Compose configuration to work correctly.
Here is a birds-eye view of all its options:
Landofile
name: "my-app"
services:
my-service:
# set type and api
api: 3
type: lando
# these directly map to docker compose things
# see: https://docs.docker.com/reference/compose-file/
# note that these are only available if you invoke the service directly
services: {}
networks: {}
volumes: {}
# below are features available in every api 3 service
app_mount: cached
# build steps
build: []
build_as_root: []
run: []
run_as_root: []
# ssl
ssl: false
sslExpose: false
# other
meUser: www-data
moreHttpPorts: []
overrides: {}Services, Networks, Volumes
These three: services, networks and volumes map directly to the Docker Compose Version 3 Spec which means that the below is a valid Landofile:
Landofile
name: lampy
services:
appserver:
api: 3
type: lando
services:
image: php:8.2-apache
command: docker-php-entrypoint apache2-foreground
ports:
- 80
database:
api: 3
type: lando
services:
image: mariadb:10.4
command: docker-entrypoint.sh mysqldNote that services, volumes and networks are only available if you use this service directly with type: lando. If you are in an upstream service we recommend you use overrides.
Also note that there are a few caveats and behavioral considerations you should be aware of while using the above:
App Mount
Lando will automatically mount your codebase in every container at /app using the :cached 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
Set app_mount to either false or disabled.
Landofile
services:
my-service:
api: 3
type: lando
app_mount: false
services:
image: php:8.2-apache
command: docker-php-entrypoint apache2-foreground
my-service2:
api: 3
type: lando
app_mount: disabled
services:
image: php:8.2-apache
command: docker-php-entrypoint apache2-foregroundMount with a different flag
Set app_mount to any valid Docker bind mount third field.
Landofile
services:
my-service:
api: 3
type: lando
app_mount: ro
services:
image: php:8.2-apache
command: docker-php-entrypoint apache2-foreground
my-service2:
api: 3
type: lando
app_mount: delegated
services:
image: php:8.2-apache
command: docker-php-entrypoint apache2-foregroundBuild Steps
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. An exception to this is if one or more of your build steps error. When this happens Lando will run the build steps on every subsequent lando start until they complete without error.
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 upbuild_as_rootruns asrootand before your service boots uprunruns as "you" and after your service boots uprun_as_rootruns asrootand after your service boots up
An example to consider is shown below:
Landofile
services:
appserver:
api: 3
type: lando
services:
image: php:8.2-apache
command: docker-php-entrypoint apache2-foreground
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:
api: 3
type: lando
services:
image: node:16
command: yarn dev
build:
- yarn
run:
- /helpers/some-helper-script.sh
run_as_root:
- echo "127.0.0.1 mysite.lndo.site" >> /etc/hostsAs you can likely surmise from the above, each step is intended for a pretty specific use case:
- Use
buildto install application dependencies that are needed before you start your application - Use
build_as_rootto install low level server packages required by your application - Use
runto install application dependencies or run build steps that require your application be started first - Use
run_as_rootfor any other post-startrootlevel 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 /app.
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:
- |
if [ ! -z $LANDO_MOUNT ]; then
do something
some other command
fiIn these situations, it is highly recommended you create a script and reference that instead. This keeps things cleaner and more portable.
#!/bin/bash
if [ ! -z $LANDO_MOUNT ]; then
do something
some other command
firun:
- /app/my-script.shUsing Dockerfiles
If you find that your build steps are approaching the length of Herman Melville's seminal work Moby Dick, 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:
Landofile
Note that build is going to be relative to your app root.
services:
appserver:
api: 3
type: lando
overrides:
build: ./php
image: pirog/php:8.2-fpm-customDockerfile
This lives inside of the ./php directory referenced in the build above.
FROM devwithlando/php:8.2-fpm
RUN apt-get update -y \
&& docker-php-ext-install pcntlEntrypoint
By default, Lando will hijack the containers entrypoint as this is how it serves its secret sauce. This does introduce some different behavior when setting the command of your service.
You can, however, set a different entrypoint.
Landofile
services:
appserver:
api: 3
type: lando
entrypoint: docker-php-entrypoint
services:
image: php:8.2-apache
command: apache2-foregroundNote that the above example will lose any Lando functionality that is provided by our default entrypoint.
Healthcheck
Since Lando 3.20.0 service URL scanning is in its own plugin.
Localhost Assignment
By default Lando will attempt to assign localhost addresses to any service that has ports 80 or 443 exposed. You can tell Lando to assign localhost addresses to additional http ports with the following.
Landofile
services:
my-service:
api: 3
type: lando
moreHttpPorts:
- 8888
services:
image: php:8.2-apache
command: apache2-foreground
ports:
- 8888Note that if you are adding additional moreHttpPorts you must also make sure that port is exposed as in the example above.
meUser
For the purposes of things like events and tooling you may wish to set the "non-root" user to run commands as "you".
Landofile
services:
my-service:
api: 3
type: lando
meUser: node
services:
image: node:16
command: npm startBy default meUser is set to www-data which exists in most services by default.
SSL
You can tell Lando to create certificates to use with ssl: true. This will also automatically expose the sport which is 443 by default. The certificates will live in /certs/* inside the container.
Landofile
services:
my-service:
api: 3
type: lando
# generate certificates
ssl: true
# expose this "secure port"
sport: 3001
# set to false to disable sport exposure
sslExpose: true
services:
image: node:16
command: npm start --https 3001Note that this does not automatically set up the service to use the certs, it merely creates the certs and exposes some ports. It is up to you to configure your service correctly to use them.
Also note that cert creation requires running the service as the root user. To work around this limitation check out this.
URL Scanning
Since Lando 3.14.0 service URL scanning is in its own plugin.
Overrides
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 overrides key.
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 networks or volumes.
Also note that if you are using this service directly it probably makes more sense to just use services, networks and volumes directly. overrides is really meant to be used in downstream services as in the example below:
Landofile
services:
html:
api: 3
# note that setting custom as the service version
# will automatically skip landos "supported" check
type: apache:custom
overrides:
environment:
STUFF: THINGS
THINGS: GUYS
image: pirog/myapache:2
volumes:
- ./mythings:/tmp/mythingsCaveats
Setting the command
By default, Lando will hijack the containers entrypoint as this is how it serves its secret sauce.
However, this means if your custom container sets its own entrypoint, you will need to remove that entrypoint and set it as the first argument in the command.
In the example below, docker-php-entrypoint is the default entrypoint for the drupal:8 image but we have moved it so that it is the first argument of command. This both allows the container to run as expected and allows Lando to do its thing.
Landofile
services:
custom-service:
api: 3
type: lando
services:
image: drupal:8
ports:
- '80'
# Required. See Below
command: docker-php-entrypoint apache2-foregroundYou can probably force the original container behavior and by extention forego the Lando magic by explicitly resetting the entrypoint.
Setting the app mount
Many Docker images will put code in /app. This directly conflicts with Lando's default codebase mount point. If you are running into a problem because of this collision, we recommend you disable the app_mount by setting it to false or disabled.
This will prevent Lando from mounting your codebase to /app so the Docker image can use its own code at /app.
Landofile
services:
pghero:
api: 3
type: lando
app_mount: false
services:
image: ankane/pghero
command: puma -C config/puma.rbChoosing the user
Many non-Lando containers do not run as the root user by default. This is OK but comes with a few caveats. The most relevant are that Lando will not be able to execute its normal boot up steps which:
- Map
host:containeruser permissions - Generate a certificate for the service
- Load user and lando managed SSH keys
Also note that containers that do not have bash installed, like some alpine ones, will similarly not be able to load up SSH keys.
These factors may or may not be relevant depending on what you are doing so they are here just as a FYI.
If you are using a container that cannot run as root but still want that Lando magic you can try something like below.
Landofile
services:
custom-service:
api: 3
type: lando
services:
user: root
image: drupal:8
# Required. See Below
command: docker-php-entrypoint apache2-foreground
ports:
- '80'
environment:
LANDO_DROP_USER: otheruser
volumes:
my-volume:
networks:
my-network:The relevant pieces here are setting user: root and then the environment variable LANDO_DROP_USER to whatever user the container is suppose to run as.
In this example the container will boot as root do the Lando things it needs to do and then run docker-php-entrypoint apache2-foreground as otheruser.
Examples
Almost all of the core tests use this service.