Используйте Docker Compose для разработки, не сойдя с ума
25 января 2023 г.Docker Compose — отличный инструмент для разработки, но я так и не нашел хорошего примера его использования для идеального рабочего процесса разработки. Контейнеры являются неизменяемыми и, следовательно, по умолчанию не являются идеальной средой разработки, поскольку разработка в основном заключается в изменении вещей и последующем запуске изменений. В большинстве блогов Docker Compose говорится о монтировании вашего репозитория кода в виде тома, который поможет вам обойти проблему неизменности и сопоставления порта, но дальше этого они не идут. Есть еще много маленьких хитростей, которые вы можете использовать, чтобы улучшить процесс разработки. Здесь я собрал все приемы, которые я использовал, чтобы сделать Docker Compose отличным рабочим процессом разработки.
Создать контейнер разработки
Ваш контейнер для разработки, скорее всего, будет отличаться от контейнеров для рабочей среды и контейнеров CI, поэтому вы можете справиться с двумя расходящимися контейнерами либо за счет многоэтапной сборки, либо за счет отдельного файла Dockerfile для разработки. Обычно я использую отдельный Dockerfile, потому что ваши производственные и CI-контейнеры часто оптимизированы для кэширования и эффективной доставки контейнера. Попытка вписать рабочий процесс разработки в это может стать неуклюжей и трудной для чистоты. Недостатком является то, что вы можете дублировать некоторый код Dockerfile между двумя файлами. Однако он должен быть небольшим, поскольку в контейнере разработки часто очень мало строк Dockerfile.
Если вы используете поэтапную сборку, используйте цель. в файле Docker Compose.
Синхронизировать разрешения пользователей
Рекомендуется не запускать от имени пользователя root, но также и для вашего контейнера разработки полезно синхронизировать пользователя контейнера с вашим локальным пользователем. Это гарантирует, что ваши файлы, смонтированные вне контейнера, будут иметь правильные разрешения. Для этого:
1. Добавьте несколько аргументов сборки в свой Dockerfile
ARG userid
ARG groupid
2. Создайте пользователя в вашем Dockerfile с доступом к sudo
# User setup
RUN addgroup mygroup --gid $groupid
RUN useradd -ms /bin/bash -u $userid -g $groupid myuser
RUN echo 'myuser ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
3. При сборке передайте аргументы сборки
docker-compose build --build-arg userid=$(id -u) --build-arg groupid=$(id -g)
Поделиться секретами
Существует атрибут secrets
, который вы можете использовать в Docker Compose, однако, поскольку он предназначен для разработки, нам не нужно защищать производственную среду, мне было проще просто смонтировать некоторые общие файлы. и каталоги. Ниже приведен пример некоторых «секретов», которыми я хотел бы поделиться.
services:
myapp:
volumes:
- .:/opt/myapp
- $HOME/.git:/home/myuser/.git
- $HOME/.ssh:/home/myuser/.ssh
- $HOME/.netrc:/home/myuser/.netrc
- $HOME/.pypirc:/home/myuser/.pypirc
Общий доступ к Git и SSH
См. выше. Если вы делитесь своими каталогами .git
и .ssh
с контейнером разработки, вы можете выполнять команды git в своем контейнере без необходимости входить и выходить из него. Это делает рабочий процесс разработки намного более приятным благодаря меньшему количеству открытых терминалов или меньшему количеству нажатий клавиш.
Установите некоторые инструменты разработки
Особенно если вы используете отдельный Dockerfile и вам не нужно беспокоиться о размере контейнера, установите дополнительные инструменты разработки. Некоторые пакеты apt, которые я люблю устанавливать: procps, nano, vim, sudo, htop, tmux, redis-tools, autojump, openssh-client, wget, unzip
И еще один из моих любимых инструментов: thef*ck
Общий доступ к средам оболочки
Поскольку у вас есть контейнер для разработки, теперь вы можете легко настроить общую среду разработки. Мне нравится включать общий .bashrc
в мой репозиторий, а затем копировать его в Dockerfile в домашний каталог пользователя.
КОПИРОВАТЬ .bashrc /home/myuser/
Запомните историю команд
Поскольку контейнеры неизменяемы, они потеряют историю команд при перестройке. Вы можете решить эту проблему, связав файл .bash_history
в своем Dockerfile.
RUN ln -s /opt/myapp/.bash_history /home/myuser/.bash_history
Полная настройка
Ниже представлена полная настройка, дополнения Dockerfile.dev
, compose.yaml
и .gitignore
.
Dockerfile.dev
FROM ubuntu:bionic
ARG userid
ARG groupid
WORKDIR /build
# apt layer
RUN apt update
RUN apt install -y python3.8 python3.8-venv libpython3.8
# dev tools
RUN apt install -y procps nano vim sudo htop tmux redis-tools autojump openssh-client wget unzip
# pip, pdm setup
RUN python3.8 -m pip install pip --upgrade
RUN pip3.8 install --upgrade pip
RUN pip3.8 install pdm thefuck
# User setup
RUN addgroup mygroup --gid $groupid
RUN useradd -ms /bin/bash -u $userid -g $groupid myuser
RUN echo 'myuser ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
WORKDIR /opt/myapp
USER myuser
COPY .bashrc /home/myuser/
RUN ln -s /opt/myapp/.bash_history /home/myuser/.bash_history
compose.yaml
version: "3.9"
services:
myapp:
network_mode: host
build:
context: .
dockerfile: Dockerfile.dev
command: /bin/bash
environment:
- DEV_CONTAINER=1
- PYTHONUNBUFFERED=1
- XDG_DATA_HOME=/opt/myapp/.local/share
volumes:
- .:/opt/myapp
- $HOME/.git:/home/myuser/.git
- $HOME/.ssh:/home/myuser/.ssh
- $HOME/.netrc:/home/myuser/.netrc
- $HOME/.pypirc:/home/myuser/.pypirc
ports:
- 8888:8888
- 8000:8000
- 8080:8080
- 8081:8081
- 3000:3000
- 5000:5000
shm_size: 4gb
depends_on:
- redis
redis:
image: 'bitnami/redis:latest'
ports:
- 6379:6379
environment:
- ALLOW_EMPTY_PASSWORD=yes
дополнения .gitignore
.bash_history
.local
Оригинал