One of my favourite things I learned working at Smile was using LXC for development. It’s different from Docker in the sense that you don’t configure services and things like that: you just create a exact copy of the environment you’re going to have in production, with all its services included. You can do that with Docker, but it’s not the same. Above all when I’m already used to LXC and don’t see the need to change.

Installing LXD / LXC packages on Ubuntu/Debian

We’re going to use snap packages for this. Just in case we’re going to remove any left over of a previous installation:

sudo apt remove --purge lxd lxd-client
sudo snap install lxd
sudo usermod --append --groups lxd [[your_user_name]]

Initial configuration

Now you have to start the initial configuration of LXD:

sudo apt install zfsutils-linux 
sudo lxd init

And you can answer the following (when there is nothing after the ‘:’, just press enter):

 Would you like to use LXD clustering? (yes/no) [default=no]: 
Do you want to configure a new storage pool? (yes/no) [default=yes]: 
Name of the new storage pool [default=default]: 
Name of the storage backend to use (btrfs, ceph, dir, lvm, zfs) [default=zfs]: 
Create a new ZFS pool? (yes/no) [default=yes]: 
Would you like to use an existing block device? (yes/no) [default=no]: 
Size in GB of the new loop device (1GB minimum) [default=21GB]: 5
Would you like to connect to a MAAS server? (yes/no) [default=no]: 
Would you like to create a new local network bridge? (yes/no) [default=yes]: 
What should the new bridge be called? [default=lxdbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
Would you like LXD to be available over the network? (yes/no) [default=no]: yes
Address to bind LXD to (not including port) [default=all]: 
Port to bind LXD to [default=8443]: 
Trust password for new clients: 
No password set, client certificates will have to be manually trusted.Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:

Create your first LXC container

Imagine you want to install a Debian 9 system. You should just execute:

sudo lxc launch images:debian/9 your_project_name

Once installed, you can ssh to it as root with:

sudo lxc exec your_project_name -- /bin/bash

You can also see that your container has a local IP assigned with lxc list:

 pau@anicha:~$ sudo lxc list
|     NAME     |  STATE  |        IPV4         |                     IPV6                      |    TYPE    | SNAPSHOTS |
| your_project_name | RUNNING | (eth0) | fd42:83d9:2888:7f0c:216:3eff:feec:899e (eth0) | PERSISTENT |           |

Setting up your container for web development

At this point we have our container where we can access as in ssh. It has an IP assigned. Now it’s only necessary to install our server packages. In this case, we can install the basic apache/php/mysql packages for Magento (in this case, with php7, but you can install whatever your Magento needs):

lxc exec your_project_name -- /bin/bash
sudo apt install php7.0 php7.0-curl php7.0-mysql libapache2-mod-php7.0 php7.0-bcmath php7.0-curl php7.0-gd php7.0-intl php7.0-mbstring php7.0-mcrypt php7.0-soap php7.0-xml php7.0-xsl php7.0-zip php7.0-json php7.0-iconv apache2   nano sudo curl wget htop net-tools mysql-client redis-tools git nano sudo curl wget htop net-tools mysql-server mysql-client -y

Now you should set up your apache server (you can follow this tutorial). This server should have a development name of your wish. I usually use: your_project_name.lxc.

Now, in your host machine (not your container), edit the /etc/hosts file. Create a new line with your container IP and the internal domain name you set up on your lxc machine. It should end up being something like this:       localhost       anicha    your_project_name.lxc

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Restart all services in your lxc and now type in your browser: your_project_name.lxc. You should see the apache or nginx info page.

Setting up a directory for development

Now imagine that you have your Magento code and your PHPStorm IDE. You don’t want to have your files only inside the LXC container. What we do in this case is to create a mapping: we create a directory in our home folder (in the host machine, not the container) and we put inside all the project files.

For example, I create the folder: /home/pau/projects/your_project_name/

If now I want to map this folder into the folder /var/www/your_project_name of the LXD machine, I have to execute the following command:

sudo lxc config device add your_project_name devfolder disk source=/home/pau/projects/your_project_name path=/var/www/your_project_name

In addition, you should map your host user with the www-data user in the lxc machine. To do that, first add the mapping:

sudo lxc config set lagourmetbox raw.idmap "both 1000 33"

And then edit the files /etc/subuid and /etc/subgid and add at the end of each one:


Now restart your container (note that some times the stop order hangs and you have to press Ctrl+C to stop it and then run it again):

sudo lxc stop --force your_project_name
sudo lxc start your_project_name

Go to your lxc machine now and check that you have the correct mapping (with the correct user) in your /var/www folder.


Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.