Docker, Unix и Git

Семинар 0 · Введение в робототехнику

Скачиваем Ubuntu

Выполните

Откройте Docker Desktop и дождитесь его запуска.
Затем откройте терминал.

Посмотреть справку Docker

docker --help

Скачать образ Ubuntu 24.04

docker pull ubuntu:24.04

После скачивания образ появится во вкладке Images в Docker Desktop.

Зачем нам Docker

Подготовленный образ с программой и её окружением

В команде

Используем согласованную среду, а не настраиваем каждый компьютер вручную.

При проверке

Запускаем программу в среде, соответствующей той, где она будет работать.

На роботе

Развёртываем проверенный образ вместо повторной установки программы и зависимостей.

Образ и контейнер

Образ

Подготовленные файлы и программы,
из которых создают контейнер.

Контейнер

Отдельная рабочая среда,
созданная из образа.

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

Где сохраняются файлы

В папке контейнера

Контейнер/tmp/result.txt

Создали файл внутри контейнера

Удалили контейнер —
этот файл пропал.

Bind mount

Папка project смонтирована в /work

В контейнере/work/result.txt
На компьютереproject/result.txt

Два пути к одному файлу

Удалили контейнер —
файл остался в папке компьютера.

Изменение или удаление файла в смонтированной папке видно с обеих сторон.

Остановка контейнера, в отличие от удаления, сохраняет его файлы.

Что запускается в контейнере

При запуске контейнера запускается выбранная программа.

Контейнер А

Работает Bash

Файлы и библиотеки Ubuntu

Контейнер Б

Работает Python-программа

Файлы и библиотеки проекта

Общее ядро Linux

Управляет процессами, памятью и доступом к устройствам

Файлы и процессы у контейнеров свои, ядро Linux — общее.

Docker на разных ОС

Docker Engine на Linux

Контейнер АКонтейнер Б
Ядро Linux компьютера

Контейнеры используют ядро
установленной Linux-системы.

Docker Desktop на Windows / macOS

Linux-среда — виртуальная машина
Контейнер АКонтейнер Б
Общее ядро Linux
Windows / macOS компьютера

Docker Desktop запускает Linux-среду.
В ней работают несколько контейнеров.

Что такое Dockerfile

Текстовый файл с инструкциями для сборки образа.

Dockerfile

FROM ubuntu:24.04
RUN apt-get update && \
    apt-get install -y git
WORKDIR /work
CMD ["bash"]
FROM
Базовый образ
RUN
Команда при сборке образа
WORKDIR
Рабочая папка
CMD
Программа по умолчанию
при запуске контейнера
Dockerfile
Сборка
Образ
Запуск
Контейнер

Dockerfile для сервера

Берём Ubuntu, устанавливаем Python и добавляем страницу сервера.

Dockerfile

FROM ubuntu:24.04
RUN apt-get update && \
    apt-get install -y python3
COPY index.html /opt/s1-http/index.html
CMD ["python3", "-m", "http.server", "8000", \
     "--bind", "0.0.0.0", \
     "--directory", "/opt/s1-http"]

COPY

Копирует файл index.html
в образ при сборке.

CMD

При запуске контейнера
стартует HTTP-сервер.

В первом примере работает Bash, во втором — сервер, который ждёт запросы.

Имя образа и платформа

ubuntu:24.04 — короткая запись полного имени:

docker.io/library/ubuntu:24.04
docker.io

Registry — Docker Hub

library

Официальные образы

ubuntu

Имя образа

24.04

Тег версии

Под одним тегом доступны варианты для разных процессоров:

linux/amd64

x86-64: процессоры AMD и Intel

linux/arm64

ARM64: например, Apple Silicon

Явно выбираем вариант, например для ARM64:

docker pull --platform linux/arm64 docker.io/library/ubuntu:24.04

Без --platform Docker выбирает платформу своей среды запуска.

Как читать docker run

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

OPTIONS

Параметры Docker

IMAGE

Из какого образа создать контейнер

COMMAND ARG...

Какую программу запустить

Пример

docker run --rm ubuntu:24.04 cat /etc/os-release

cat покажет сведения об Ubuntu. После завершения контейнер удалится.
Если программу не указать, используется команда по умолчанию из образа.

Справка: docker run --help

Параметры запуска

docker run -it --name s1-ubuntu ubuntu:24.04 bash
-i
Сохранять открытым стандартный ввод
-t
Выделить терминал; -it объединяет -i и -t
--name s1-ubuntu
Назвать контейнер s1-ubuntu
--rm
Удалить контейнер после завершения
-d
Запустить в фоне и вернуть управление терминалу
-w /work
Начать работу в папке /work контейнера
-e ROBOT_NAME=demo
Задать переменную окружения ROBOT_NAME

Полный список параметров: docker run --help

Два терминала — один контейнер

Первый терминал

docker run -it --name s1-ubuntu ubuntu:24.04 bash

В открывшемся Bash создайте файл:

touch /tmp/seminar-marker

Второй терминал

docker exec -it s1-ubuntu bash

Во втором Bash проверьте файл:

ls /tmp/seminar-marker

Два процесса Bash работают в одном контейнере и видят его файлы.

Создать, запустить, выполнить

docker run
Создать новый контейнер из образа и запустить его
docker start
Запустить существующий остановленный контейнер
docker exec
Запустить ещё одну программу в работающем контейнере

Посмотреть контейнеры

docker ps
docker ps -a

Работающие / все, включая остановленные

Вернуться в остановленный контейнер

docker start -ai s1-ubuntu

Тот же контейнер, созданный ранее файл сохраняется.

Папки, переменные и сеть

-v "$(pwd):/work:ro"
Смонтировать текущую папку в /work
:ro — только чтение
-w /work
Выбрать рабочую папку внутри контейнера
-e ROBOT_NAME=demo
Передать переменную окружения
--env-file .env
Прочитать переменные из файла .env
-p 127.0.0.1:8080:8000
Направить порт 8080 компьютера
на порт 8000 контейнера
--network none
Запустить без внешней сети

Параметры Docker указываются перед именем образа.

Ресурсы и устройства

--cpus 2
Ограничить процессорное время: до двух CPU
--memory 1g
Ограничить оперативную память: 1 ГиБ
--user 1000:1000
Запустить от пользователя и группы
с указанными идентификаторами
--gpus all
Предоставить доступ к поддерживаемым GPU
--device /dev/ttyUSB0
Предоставить доступ к Linux-устройству
--platform linux/amd64
Выбрать архитектуру запускаемого образа

GPU, устройства и эмуляция требуют поддержки среды запуска.
Все параметры: docker run --help

Bind mount: одна папка, два пути

Bind mount делает папку компьютера доступной внутри контейнера.

На компьютереseminar-01
В контейнере/work

Параметры команды docker run:

-v "$(pwd):/work"

Слева — текущая папка компьютера; справа — путь внутри контейнера.
$(pwd) — запись для macOS / Linux.

-w /work

Начать работу в папке /work внутри контейнера.

Файлы не копируются: изменения видны с обеих сторон.

Порты и режим сети

Публикация порта

-p 127.0.0.1:8080:8000

Компьютер :8080

Контейнер :8000

127.0.0.1 — доступ только
с этого компьютера.

Сеть компьютера

--network host

На Linux контейнер использует
сетевое пространство компьютера.

Публикация через -p не нужна.
Конфликты портов — общие.

Публикация порта не запускает программу.
В Docker Desktop режим host требует отдельного включения.

Логи и остановка

Команды управления существующим контейнером:

docker logs --tail 5 s1-ubuntu
Последние пять строк вывода
docker logs -f s1-ubuntu
Следить за новыми сообщениями
docker stop s1-ubuntu
Остановить контейнер
docker ps -a
Показать все контейнеры,
включая остановленные

stop не удаляет контейнер и его файлы.
Ctrl+C при просмотре логов завершает просмотр, а не контейнер.

Тот же контейнер в Compose

Параметры запуска можно записать в файл compose.yaml.

services:
  workspace:
    image: ubuntu:24.04
    command: bash
    stdin_open: true
    tty: true
    volumes: [".:/work"]
    working_dir: /work

Это отдельный пример конфигурации. Сейчас его не запускаем.

Запускаем контейнер для практики

Выполните

Скачайте файлы практики, распакуйте архив.
Откройте терминал в папке seminar-01.

macOS / Linux:

docker run -it --name s1-class -v "$(pwd):/work" -w /work ubuntu:24.04 bash

Внутри контейнера:

pwd
bash /work/prepare-files.sh
touch /work/scratch/from-container.txt

Проверьте файл на компьютере: seminar-01/scratch/from-container.txt.
Этот контейнер сохраняем для практики по Unix и Git.

Устанавливаем программы

Выполните

Выполняем в Bash контейнера s1-class.

unminimize
apt-get update
apt-get install -y git nano less man-db manpages python3

unminimize восстанавливает справочные страницы Ubuntu.
На запросы подтверждения отвечаем y.

Проверяем справку:

man wc

Клавиша q — вернуться из справки в Bash.

Из чего состоит команда

ls

Команда

Показать содержимое

-l

Опция

В подробном формате

/work

Аргумент

Папки /work

У опции может быть значение:

head

Команда

-n

Опция

5

Значение
опции -n

methane.pdb

Аргумент: файл

Показать первые 5 строк файла methane.pdb.

Как читать путь

Текущая папка: /work

Абсолютный путь

cd /work/shell-lesson-data

От корня /.
Не зависит от текущей папки.

Относительный путь

cd shell-lesson-data

От текущей папки — здесь /work.
Зависит от того, где мы находимся.

Из /work обе команды ведут в одну папку.

. — текущая папка.. — родительская~ — домашняя

Найдите папку с молекулами

Самостоятельно

Текущая папка: /work

  1. Найдите каталог alkanes в данных урока и перейдите в него.
  2. Покажите полный путь к текущей папке и её содержимое.

В найденной папке должны быть файлы .pdb.

Путь к данным

Из папки /work:

cd shell-lesson-data/exercise-data/alkanes

Проверяем путь

pwd

Текущая папка

/work/shell-lesson-data/
exercise-data/alkanes
ls

Здесь находятся methane.pdb, ethane.pdb и другие .pdb-файлы.

Работаем с копией файла

Исходный methane.pdb оставляем в alkanes.

Создаём копию

mkdir -p /work/scratch
cp methane.pdb /work/scratch/
cd /work/scratch

Дальше работаем в /work/scratch.

Редактируем, переименовываем, удаляем

nano methane.pdb
mv methane.pdb molecule-copy.pdb
rm molecule-copy.pdb

rm удаляет файл, не перемещая в корзину.

Ctrl+Oсохранить в nanoEnterподтвердить имяCtrl+Xвыйти

Создайте свою копию

Самостоятельно

Текущая папка: alkanes. Папка /work/scratch уже существует.

Источник

ethane.pdb

Новая копия

/work/scratch/my-molecule.pdb
  1. Скопируйте файл под новым именем.
  2. Проверьте, что существуют и исходник, и копия.

Не редактируйте и не удаляйте файлы.

Исходник и копия

cp ethane.pdb /work/scratch/my-molecule.pdb

Проверить оба пути

ls ethane.pdb /work/scratch/my-molecule.pdb

Оба файла существуют.

Открыть копию

cat /work/scratch/my-molecule.pdb

В терминале появится её содержимое.

cp может завершиться без сообщения. Проверяем созданный файл.

Как посмотреть текст

Начало файла

head -n 5 methane.pdb

Первые пять строк.

Конец файла

tail -n 5 methane.pdb

Последние пять строк.

Просмотр и поиск

less methane.pdb

Чтение без изменения файла.

В less:

Spaceвперёдbназад/ATOMнайти ATOMnследующее совпадениеqвыйти

Размер файла, папки и диска

Файл

ls -l methane.pdb

Логический размер файла в байтах.

Дерево папки

du -sh .

Занятое место — один итог.

По папкам первого уровня:

du -h --max-depth=1 /work

Файловая система

df -h /work

Ёмкость, занятое и свободное место.

Size · Used · Avail · Use%

Сколько места занимает папка?

Самостоятельно

Текущая папка: alkanes

  1. Узнайте, сколько места занимает всё дерево текущей папки.
  2. Получите один итог в читаемых единицах.

Нужно место, занятое папкой, а не свободное место диска.

Один итог для текущей папки

du -sh .
du

Занятое место

-s

Один итог

-h

Читаемые единицы

.

Текущая папка

Форма ответа

[размер]  .

Это размер дерева папки. Свободное место файловой системы показывает df.

Права на запуск файла

/tmp/s1-permissions/hello.sh · - в начале прав означает обычный файл.

Владелец · u

rw-

Группа · g

r--

Остальные · o

r--
chmod u+x hello.sh

r — чтение · w — запись · x — исполнение · u+x — добавить x владельцу

Прямой запуск

./hello.sh

Требует права x у файла.

Через интерпретатор

bash hello.sh

Bash читает файл; его x не требуется.

Разрешите прямой запуск

Самостоятельно

Папка: /tmp/s1-permissions. Файл hello.sh пока без права исполнения.

  1. Добавьте право исполнения только владельцу.
  2. Запустите файл напрямую.
  3. Проверьте приветствие и права файла.

Право исполнения у владельца

Изменить и запустить

chmod u+x hello.sh
./hello.sh

Результат

Hello from the container

Проверить права

ls -l hello.sh
-rwxr--r--

Появился x в тройке владельца.

Выполните
cd /work/shell-lesson-data/exercise-data/alkanes
pwd

Что считает wc

wc methane.pdb
9

Переводы строки

-l / --lines
57

Слова

-w / --words
422

Байты

-c / --bytes
methane.pdb

Имя файла

-m / --chars — число символов. Байты и символы могут различаться.

Слова разделяются пробельными символами.

Где найти нужную опцию

Краткая справка

wc --help

Названия опций и их назначение.

-l · -w · -c · -m

Страница руководства

man wc

WC(1): 1 — раздел руководства, не версия.

Spaceвперёдbназад/--linesпоиск в manqвыйти

Для встроенной команды Bash: help cd.

Шаблон вместо списка файлов

wc -l methane.pdb ethane.pdb

Можно передать несколько имён — или использовать шаблон:

wc -l *.pdb

Шаблон Bash

*.pdb

Совпавшие имена подставляются до запуска wc.

Файлы в текущей папке

cubane.pdbethane.pdbmethane.pdboctane.pdbpentane.pdbpropane.pdb

total в выводе wc — сумма, а не имя файла.

Найдите опцию для строк

Самостоятельно

Текущая папка: alkanes. Файл: propane.pdb

  1. Откройте wc --help.
  2. Найдите опцию подсчёта строк.
  3. Посчитайте строки в propane.pdb.

Нужны строки, не байты.

Две формы одной опции

Короткая

wc -l propane.pdb

Длинная

wc --lines propane.pdb

Результат

15 propane.pdb

-l и --lines считают переводы строки.

Три стандартных потока

Команда cat без имени файла читает стандартный ввод.

stdin

hello

Текст на входе

Программа

cat

stdout

hello

Обычный результат

stderr — отдельный поток

Сюда программа пишет сообщения об ошибках.

Без перенаправлений ввод идёт с клавиатуры, а stdout и stderr видны в терминале.

Сохраняем вывод в файл

wc -l *.pdb > /work/results/lengths.txt

stdout команды

wc -l *.pdb

Таблица счётчиков

Файл результата

/work/results/lengths.txt

Bash записывает таблицу сюда.

cat /work/results/lengths.txt
> создать или перезаписать>> дописать в конец

Сохраните результат в файл

Самостоятельно

Текущая папка: alkanes. Папка /work/results уже существует.

  1. Посчитайте строки файла ethane.pdb.
  2. Запишите результат в /work/results/ethane-lines.txt.
  3. Покажите содержимое созданного файла.

Исходный .pdb не изменяйте.

Вывод оказался в файле

wc -l ethane.pdb > /work/results/ethane-lines.txt

Прочитать файл

cat /work/results/ethane-lines.txt

Содержимое отчёта

12 ethane.pdb

Перенаправление меняет место вывода, но не текст wc.

Сортировать как текст или как числа

Один и тот же файл: ../numbers.txt

Как текст

sort ../numbers.txt

Результат

10
19
2
22
6

Как числа

sort -n ../numbers.txt

Результат

2
6
10
19
22

Для таблицы счётчиков нужен sort -n. sort не изменяет исходный файл.

Pipe соединяет две команды

cat ../numbers.txt | sort -n

stdout команды cat

cat ../numbers.txt

Печатает числа

stdin команды sort

sort -n

Получает этот текст и сортирует

| передаёт текст следующей команде, не создавая промежуточный файл.

Выполните
wc -l *.pdb > /work/results/lengths.txt
cat /work/results/lengths.txt

Оставьте первую строку

Самостоятельно

Файл /work/results/lengths.txt уже создан.

  1. Численно отсортируйте всю таблицу.
  2. Выведите только первую строку результата.

Новый файл не создавайте.

Сначала sort, затем head

sort -n /work/results/lengths.txt | head -n 1

Вся таблица

sort -n

Упорядочить все строки

Первая строка

head -n 1

Оставить одну строку

Результат

9 methane.pdb

Три самых коротких файла

Самостоятельно

Текущая папка: alkanes

  1. Найдите три .pdb-файла с наименьшим числом строк.
  2. Сохраните три строки результата в /work/results/shortest.txt.
  3. Покажите содержимое файла.

Исходные .pdb не изменяйте.

От файлов к короткому отчёту

wc -l *.pdb | sort -n | head -n 3 > /work/results/shortest.txt
wc -l

Посчитать строки

sort -n

Упорядочить

head -n 3

Оставить три

>

Записать в файл

Открыть отчёт

cat /work/results/shortest.txt

Три строки

9 methane.pdb
12 ethane.pdb
15 propane.pdb

Git: история проекта

Сохраняем рабочие версии и понимаем, что изменилось.

Изменить

Настроили поворот робота или исправили программу.

Сравнить

Посмотрели, чем новая версия отличается от рабочей.

Вернуться

Нашли прежнюю версию, если изменение оказалось неудачным.

История с понятными сообщениями — вместо папок «final», «final2» и «точно_final».

Репозиторий и коммит

Репозиторий

Проект, для которого Git хранит историю изменений.

git-demo/
  README.md
  .git/

.git — служебные данные Git; вручную их не меняем.

Коммит

Сохранённый снимок подготовленного состояния проекта.

Первая версияДобавили описание

У него есть идентификатор, автор, сообщение и связь с предыдущей историей.

Ветка — имя, указывающее на коммит. При новом коммите указатель текущей ветки перемещается.

Git и GitHub

Git · локально

Программа, которая хранит историю репозитория.

git add README.md
git commit -m "Add seminar note"

Для локальных коммитов не нужны аккаунт и интернет.

GitHub / GitLab · в сети

Сервисы для размещения репозиториев и совместной работы.

Удалённый репозиторий — другая копия проекта с историей.

push отправляет коммиты в неё; pull получает и объединяет изменения.

Коммит ≠ публикация. Сначала научимся работать с локальной историей.

Как появляется коммит

Рабочая папка

README.md

Редактируем файл.

git add

Индекс

Содержимое, выбранное для следующего коммита.

git commit

История

Сохранённые снимки проекта.

git diff

Рабочая папка ↔ индекс

git diff --staged

Индекс ↔ последний коммит

После новой правки git add нужно повторить: индекс сам не обновится.

Создаём репозиторий

Выполните

В контейнере s1-class · отдельная пустая папка /work/git-demo

mkdir -p /work/git-demo
cd /work/git-demo
git init -b main
git config user.name "Seminar Student"
git config user.email "student@example.invalid"
nano README.md

Введите в README.md строку My first seminar. Сохраните файл и выйдите.

-b main — начальная ветка. Имя и email — учебные; настройки автора локальные.

Первый коммит

Выполните

Папка /work/git-demo · README.md сохранён, коммитов ещё нет.

Подготовить содержимое

git status
git add README.md
git diff --staged

untracked — файл ещё не отслеживается. После add он подготовлен к коммиту.

Сохранить и проверить

git commit -m "Add seminar note"
git status
git log --oneline

-m задаёт сообщение; --oneline показывает историю кратко.

В истории появилась запись, а новых изменений для коммита нет.

Сохранить файл ≠ сделать коммит

Представим, что после первого коммита изменили строку в README.md.

− My first seminar
+ My first seminar: Docker, Unix and Git

До git add

git diff

Показывает новую правку.

git diff --staged

Изменений для коммита пока нет.

После git add README.md

git diff

Пусто: файл и индекс совпадают.

git diff --staged

Показывает подготовленную правку.

Новый коммит добавит версию в историю, а не перепишет первый коммит.

Ветки на схеме

Learn Git Branching · симулятор в браузере

C0C1mainHEAD → main

Коммит

Узел графа. Стрелка направлена к родителю.

Ветка

Имя, которое указывает на коммит. Сейчас это main.

HEAD

Показывает, где мы работаем. Обычно связан с текущей веткой.

В симуляторе git commit создаёт узел без редактирования файла и add.

Создаём ветку

В симуляторе: main на C1, HEAD → main.

git commit

Новый C2; main перемещается на него.

git branch feature

Создаём имя feature на C2.

git checkout feature

Переключаемся на feature.

git commit

Новый C3; перемещается только feature.

C0C1C2mainC3featureHEAD → feature

Ветка — не копия папки. Создание ветки само по себе не создаёт коммит.

Объединяем ветки

В симуляторе: feature на C3, main на C2.

git checkout main
git commit
git merge feature
C2C3C4C5featureHEAD → main

C5 связывает две линии истории. Меняется main — текущая ветка; feature остаётся на C3.

Если истории не разошлись, возможен fast-forward: сдвиг ветки без нового коммита слияния.

Добавьте две версии

Самостоятельно

Learn Git Branching → Введение → «Знакомство с Git Commit»

Начало

C0 ← C1

main → C1 · HEAD → main

Цель

C0 ← C1 ← C2 ← C3

main → C3 · HEAD → main

Добейтесь целевого графа. Перед каждой командой предскажите, какой узел и какая метка изменятся.

Два новых коммита

git commit
git commit
C0C1C2C3mainHEAD → main

Родитель C2 — C1, родитель C3 — C2. После каждого коммита main перемещается вперёд.

Дополнительно: задача про ветку →

Создайте ветку bugFix

Дополнительно

Learn Git Branching → Введение → «Ветвление в Git»

  1. Начните уровень с C0 ← C1, где main → C1 и HEAD → main.
  2. Создайте ветку bugFix и переключитесь на неё.
  3. Не добавляйте новых коммитов.

Сохраните точное имя: bugFix. Регистр букв имеет значение.

Новая ветка, прежний коммит

git branch bugFix
git checkout bugFix
C0C1main · bugFixHEAD → bugFix

git branch bugFix

Добавляет имя ветки на текущий коммит.

git checkout bugFix

Переключает HEAD на эту ветку.

Коммитов осталось два. Оба имени веток указывают на C1.