Создаём рабочее окружение в lxc контейнере
RichApp
Опубликована 25 февраля 2020 в 12:24:13Обновлена 15 апреля 2020 в 17:19:53

Создаём рабочее окружение в lxc контейнере

envlinuxlxc
LXC. Что это?

Разработчик начинает проект с настройки окружения. Окружение проекта состоит из операционной системы, программ, языков программирования. 

Мы рассмотрим настройку окружения на примере ОС Ubuntu 18.04. На систему мы установим PostgreSQL 11, Nginx, Nodejs, Golang. Установленные программы будут использоваться для примеров в других статьях.

Контейнеры в lxc создаются из образов. Образ - это слепок ОС. Его можно создать из контейнера. Образы можно распространять на другие машины. Для этого в lxc есть два механизма. Первый - экспорт образа в архив. Второй - создание сервера образов.

Lxc контейнер максимально близок к стандартной установке Linux. Программы в контейнере работают как в полноценной ОС. При старте контейнера происходит инициализация системы.

Ссылка на видео ролик: https://youtu.be/qHjus7Qu1KQ.

Установка lxd

На этом шаге мы установим lxd. Для установки вам необходима ОС linux. Мой пример работает в ubuntu 18.04. Пользователи windows и mac OS могут запустить ubuntu 18.04 с помощью VMware или VirtualBox.

Установим lxd из snap. Сделаем настройки для запуска непривилегированных контейнеров. Добавим нашего пользователя в группу lxd. Это сделает возможным запуск lxd команд под пользователем. Затем мы инициализируем lxd.

sudo snap install lxd

# Настройки для запуска непривилегированных конейнеров
echo "1000:$(id -u):1" | sudo sh -c 'cat >> /etc/subuid'
echo "root:$(id -u):1" | sudo sh -c 'cat >> /etc/subuid'
echo "1000:$(id -g):1" | sudo sh -c 'cat >> /etc/subgid'
echo "root:$(id -g):1" | sudo sh -c 'cat >> /etc/subgid'

sudo usermod -aG lxd $(whoami)
# заменяю sg lxd
# на открытие новой консоли
exit

# Открываете новую консоль
# Выбираю всё по умолчанию кроме storage backend
# Потому что для btrfs нужно сразу выделить место
# Name of the storage backend to use (btrfs, dir, lvm) [default=btrfs]: dir
lxd init

Теперь пользователь root в контейнере будет соответствовать uid и gid пользователя ОС. Пользователь с id 1000 в контейнере будет соответствовать uid и gid пользователя ОС.

Создание базового образа

На этом шаге мы выкачиваем образ с ubuntu 18.04 и создаём из него контейнер base. Заходим в контейнер под root. Меняем имя и группу пользователя в контейнере.

lxc launch ubuntu:18.04 base
lxc exec base -- sudo --login

# меняем имя с ubuntu на stepan
usermod -l stepan -m -d /home/stepan ubuntu
groupmod -n stepan ubuntu
exit

lxc exec base -- sudo --login
# задаем одноименный пароль пользователю
passwd stepan

# файлу добавляем права на запись, чтобы отредактировать
chmod o=rw /etc/sudoers.d/90-cloud-init-users

Меняем файл /etc/sudoers.d/90-cloud-init-users.

stepan ALL=(ALL) NOPASSWD:ALL

Возвращаем права на файл и выходим из контейнера.

chmod o=r /etc/sudoers.d/90-cloud-init-users
exit

Заходим в контейнер под пользователем.

lxc exec base -- sudo --login --user stepan

В контейнере меняем настройки ssh в файле /etc/ssh/sshd_config.

PasswordAuthentication yes

В контейнере перезапускаем ssh сервис.

sudo service ssh restart

В контейнере настраиваем локали, изменив файл /etc/default/locale.

LANG=ru_RU.UTF-8
LC_CTYPE="C.UTF-8"
LC_NUMERIC=en_US.UTF-8
LC_TIME=ru_RU.UTF-8
LC_COLLATE="C.UTF-8"
LC_MONETARY=ru_RU.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=ru_RU.UTF-8
LC_NAME=ru_RU.UTF-8
LC_ADDRESS=ru_RU.UTF-8
LC_TELEPHONE=ru_RU.UTF-8
LC_MEASUREMENT=ru_RU.UTF-8
LC_IDENTIFICATION=ru_RU.UTF-8

Применяем локали и устанавливаем timezone в контейнере.

sudo locale-gen en_US.UTF-8 ru_RU.UTF-8
sudo timedatectl set-timezone Europe/Moscow
sudo service rsyslog restart

Устанавливаем базовые программы в контейнере и выходим из него.

sudo apt update
sudo apt install -y python3-pip
sudo apt install -y mc
sudo apt install -y git
exit

На следующем шаге мы создаём из контейнера образ и экспортируем этот образ в архив.

lxc stop base
lxc publish base --alias base-image
lxc image export base-image base-image

Создание образа проекта

Создаём контейнер проекта из базового образа и заходим в него.

lxc launch base-image project
lxc exec project -- sudo --login --user stepan

В контейнере устанавливаем PostgreSQL.

sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt update
sudo apt install -y postgresql-11

Убираем вход по паролю в PostgreSQL для пользователя postgres. Меняем строку в /etc/postgresql/11/main/pg_hba.conf.

local   all             postgres                                peer

На строки.

local   all             postgres                                trust
host    all             postgres        127.0.0.1/32            trust

Применяем настройки и проверяем их.

sudo service postgresql reload
psql -U postgres
\q
psql -U postgres -h localhost
\q

В контейнере устанавливаем Nginx, Nodejs.

sudo apt install -y nginx
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt install -y nodejs

В контейнере устанавливаем Golang.

cd /usr/local
sudo wget https://dl.google.com/go/go1.13.8.linux-amd64.tar.gz
sudo tar xf go1.13.8.linux-amd64.tar.gz
sudo rm go1.13.8.linux-amd64.tar.gz
sudo ln -s /usr/local/go/bin/go /usr/local/bin/go
sudo ln -s /usr/local/go/bin/godoc /usr/local/bin/godoc
sudo ln -s /usr/local/go/bin/gofmt /usr/local/bin/gofmt
sudo mkdir /usr/local/golib
sudo chown $(id -un):$(id -gn) /usr/local/golib

Добавляем переменные для golang в ~/.bashrc.

export GOPATH=/usr/local/golib

Применяем настройку и устанавливаем go пакеты.

. ~/.bashrc
sudo apt install -y pkg-config libzmq3-dev
go get github.com/lib/pq
go get github.com/pebbe/zmq4
go get github.com/pquerna/ffjson
go get github.com/xeipuuv/gojsonschema
go get github.com/golang/protobuf/protoc-gen-go

Устанавливаем python3 модули и выходим из контейнера.

sudo pip3 install asyncpg
sudo pip3 install pyzmq
sudo pip3 install ujson
sudo pip3 install jsonschema
sudo pip3 install protobuf
sudo pip3 install aiofiles
sudo pip3 install invoke
sudo pip3 install fabric
sudo pip3 install prompt_toolkit
sudo pip3 install pyinstaller
exit

На следующем шаге мы создаём из контейнера образ и экспортируем этот образ в архив.

lxc stop project
lxc publish project --alias project-image
lxc image export project-image project-image

Заключение

Созданные архивы с образами - бэкап нашего окружения. Архивы можно использовать для распространения образов. Для импорта образа из архива вводится команда:

lxc image import project-image.tar.gz --alias project-image

Ссылки