Введение
Ваша команда готовит небольшое HTTP-приложение к поставке. Упакуйте предоставленный код в образ контейнера, сохраните его в Amazon Elastic Container Registry (ECR) и докажите, что именно сохранённая версия запускается и отвечает на запрос. Не изменяйте отдельный эталонный репозиторий и в конце удалите созданные вами ресурсы.
Сначала пройдите AWS Foundations и основы политик идентификации IAM. Понятия Docker объясняются здесь; писать приложение или иметь личный аккаунт AWS не требуется. Независимая VM предоставляет настроенную AWS CLI, Docker, Dockerfile и исходный код. В верхней области AWS View наблюдайте за репозиториями и тестируйте приложение, а в нижней Terminal выполняйте команды. Обе области читают одно состояние ресурсов.
Связь с сертификацией
| Сертификация | Задача экзамена | Практика |
|---|---|---|
| Developer – Associate (DVA-C02) | Задача 3.1, навык 3.1.1 | Упаковать код приложения и среду выполнения в образ контейнера для развёртывания. |
Обзор лабораторной работы

Создать неизменяемый репозиторий образов
На этом шаге создайте репозиторий для версии приложения.
Образ объединяет файлы приложения и среду выполнения. Контейнер — работающий экземпляр образа. Реестр хранит и распространяет образы; репозиторий ECR группирует образы одного приложения. Сохранение образа не запускает приложение.
Перейдите в подготовленную рабочую папку и изучите Dockerfile. cat выводит текстовый файл:
cd /home/labex/project
cat application/Dockerfile
FROM выбирает базовый образ Python, COPY добавляет приложение, USER выбирает непривилегированного пользователя, а CMD задаёт команду запуска. Базовая ссылка sha256 фиксирует содержимое базового образа, а не вашего нового образа приложения.
Создайте ct-demo. Тег — читаемое имя, например release-1. IMMUTABLE запрещает заменять существующий тег другим содержимым и сохраняет надёжность имён версий:
aws ecr create-repository \
--repository-name ct-demo \
--image-tag-mutability IMMUTABLE
Ответ содержит repositoryUri, адрес для Docker, и imageTagMutability: IMMUTABLE. Сохраните URI в переменной оболочки. $(...) захватывает вывод команды, --query выбирает поле, а --output text возвращает его без кавычек JSON:
REPOSITORY_URI=$(aws ecr describe-repositories \
--repository-names ct-demo \
--query 'repositories[0].repositoryUri' \
--output text)
echo "$REPOSITORY_URI"
Не закрывайте эту сессию Terminal, чтобы сохранить переменные. В верхней AWS View должен появиться ct-demo с нулём образов рядом с ct-reference. Эталонный репозиторий принадлежит другому приложению и не входит в область очистки.
Собрать и опубликовать версию
На этом шаге соберите предоставленное приложение и отправьте образ в ECR.
Перед отправкой Docker должен войти в реестр. Адрес реестра — часть URI до первой косой черты. ${REPOSITORY_URI%%/*} удаляет её и всё после неё:
REGISTRY=${REPOSITORY_URI%%/*}
echo "$REGISTRY"
Получите временный пароль ECR через AWS CLI и передайте его напрямую Docker. Канал | направляет вывод следующей команде; --password-stdin не позволяет паролю попасть в аргументы или вывод Terminal. Не выводите и не сохраняйте его самостоятельно:
aws ecr get-login-password | docker login \
--username AWS \
--password-stdin "$REGISTRY"
Docker выводит Login Succeeded. Это разрешает операции, доступные вашей идентификации, но не доступ ко всем репозиториям.
Соберите образ из application. -t присваивает URI и тег версии. Последний аргумент — контекст сборки, каталог с файлами, доступными для COPY:
docker build -t "${REPOSITORY_URI}:release-1" application
Отправьте образ. Docker загружает слои файловой системы и manifest, описывающий содержимое:
docker push "${REPOSITORY_URI}:release-1"
В конце Docker выводит digest sha256:.... Digest идентифицирует точное содержимое, а тег — имя. Даже если репозиторий разрешает менять теги, digest остаётся связанным с исходным содержимым.
Запросите ECR, чтобы подтвердить сохранённую версию:
aws ecr describe-images \
--repository-name ct-demo \
--image-ids imageTag=release-1 \
--query 'imageDetails[0].{Tags:imageTags,Digest:imageDigest}'
Также сохраните digest в переменной:
IMAGE_DIGEST=$(aws ecr describe-images \
--repository-name ct-demo \
--image-ids imageTag=release-1 \
--query 'imageDetails[0].imageDigest' \
--output text)
Digest ECR должен совпадать с выводом docker push. В верхней AWS View репозиторий ct-demo содержит release-1 и его digest. Приложение ещё не работает; вы запустите его далее.
Запустить точный опубликованный образ
На этом шаге получите образ по digest и проверьте настоящий контейнер приложения.
Сначала удалите локально собранный образ. docker image rm удаляет локальную ссылку, но не образ в ECR. Следующая загрузка получит опубликованную версию:
docker image rm "${REPOSITORY_URI}:release-1"
Объедините URI и digest через @, чтобы выбрать точное содержимое:
docker pull "${REPOSITORY_URI}@${IMAGE_DIGEST}"
Docker сообщает тот же digest и успешную загрузку. Запустите его как ct01-app. --detach запускает в фоне; --publish 127.0.0.1:8081:8000 связывает порт хоста 8081 с портом приложения 8000. Loopback ограничивает прямой доступ этой VM. В образе уже выбран непривилегированный пользователь; --read-only делает корневую файловую систему доступной только для чтения, --cap-drop ALL удаляет Linux capabilities, а no-new-privileges запрещает получать дополнительные привилегии:
docker run --detach \
--name ct01-app \
--read-only \
--cap-drop ALL \
--security-opt no-new-privileges \
--memory 256m \
--publish 127.0.0.1:8081:8000 \
"${REPOSITORY_URI}@${IMAGE_DIGEST}"
ID контейнера означает, что Docker принял запуск, но не доказывает исправность приложения. Проверьте HTTP: curl --fail завершается ошибкой при HTTP-ошибке; --retry-all-errors повторяет ошибки подключения при запуске, включая краткий сброс соединения:
curl --fail --silent --show-error \
--retry 5 --retry-all-errors --retry-delay 1 \
http://127.0.0.1:8081/
Ожидайте JSON с "release": "release-1" и именем хоста контейнера. Посмотрите журналы, чтобы подтвердить настоящий запрос:
docker logs ct01-app
Должно появиться served application request. Имя хоста и время могут отличаться. В верхней AWS View выберите Request application. Ответ также должен содержать release-1; кнопка отправляет настоящий HTTP-запрос контейнеру.

Удалить ресурсы приложения
На этом шаге остановите приложение и удалите его локальный образ и репозиторий ECR, сохранив эталонный репозиторий.
Сначала остановите контейнер:
docker stop ct01-app
Затем удалите его. Удаление контейнера не удаляет образ:
docker rm ct01-app
Теперь работающих контейнеров, использующих образ, нет; удалите локальную ссылку по digest:
docker image rm "${REPOSITORY_URI}@${IMAGE_DIGEST}"
Удалите образ из ECR по digest. imageDigest выбирает точное содержимое независимо от тега:
aws ecr batch-delete-image \
--repository-name ct-demo \
--image-ids imageDigest="$IMAGE_DIGEST"
Ответ должен перечислить удалённый образ в imageIds и пустой список failures. Удалите теперь пустой репозиторий приложения:
aws ecr delete-repository --repository-name ct-demo
Убедитесь, что эталонный репозиторий сохранился:
aws ecr describe-repositories \
--query 'repositories[].repositoryName'
Ожидайте только ct-reference. В завершение удалите сохранённую Docker авторизацию в реестре:
docker logout "$REGISTRY"
В верхней AWS View должны исчезнуть ct-demo и контейнер приложения, а эталонный репозиторий — остаться. Одна лишь HTTP-ошибка не доказывает очистку: вы также проверили инвентарь и удалили настоящий контейнер и образ.
Резюме
Вы создали неизменяемый репозиторий ECR, собрали и опубликовали образ, сравнили digest и запустили именно эту версию. Вы проверили настоящие ответы HTTP и журналы, затем удалили свой контейнер, локальный образ и репозиторий, сохранив репозиторий другого приложения. Следующая лабораторная работа использует определение задачи ECS для выбора и запуска образа.
Подробнее см. в документации AWS: Аутентификация реестра и отправка образов; Предотвращение перезаписи тегов образов.



