Prywatny rejestr Docker – Amazon Elastic Container Registry

W projektach, które tworzę na dobre zadomowił się Docker. Wspomaga nas w utrzymywaniu identycznego środowiska developerskiego, w łatwych eksperymentach z zewnętrznymi usługami. Co najważniejsze, w kontekście tego artykułu – Docker umożliwia nam także, tworzenie finalnych artefaktów aplikacji.

Każde nowe wydanie aplikacji to utworzony Docker Image, nazwany i otagowany odpowiednią wersją, który finalnie publikowany jest w repozytorium obrazów. Jednym z takich repozytoriów jest Docker Hub czy opisywany AWS ECR. Dzięki takiemu rejestrowi tworzymy bazę wydań naszej aplikacji, którą możemy uruchomić w kontenerze Docker, zazwyczaj za pomocą jednego polecenia docker run.

W tym artykule opiszę w jaki sposób rozpocząć pracę z repozytorium prywatnych obrazów Docker – AWS ECR.

Czym jest ECR?

Elastic Container Registry (w skrócie: ECR) jest zarządzanym prywatnym rejestrem obrazów Docker. Działa na podobnej zasadzie co Docker Hub z tą różnicą, że w ECR mówimy tylko PRYWATNYCH obrazach, czyli takich do których bez uwierzytelnienia nie mamy dostępu. Do rejestru możemy zapisać obraz oraz go pobrać wykorzystując Docker CLI.

Zastosowanie usługi ECR ułatwia nam uruchamianie skonteneryzowanych aplikacji za pomocą takich usług jak ECS (Amazon Elastic Container Service), EKS (Amazon Elastic Kubernetes Service) czy AWS Elastic Beanstalk.

AWS CLI

Podstawowym rozwiązaniem do zarządzania usługami AWS jest konsola AWSa. Za jej pomocą, praktycznie wszystkie kroki jesteśmy w stanie wykonać za pomocą webowego interfejsu AWS.

Natomiast, do podstawowej obsługi usług AWS, polecam AWS CLI. Narzędzie, którego obsługa staje się intuicyjna po wydaniu kilku poleceń. Opis instalacji oraz konfiguracji znajdziesz w dobrze przygotowanej dokumentacji AWS.

Tworzenie repozytorium

Aby móc rozpocząć jakiekolwiek dalsze działania, potrzebujemy jednego, niezbędnego składnika – nowego repozytorium w usłudze ECR. Miejsca gdzie, będziemy publikować wersje danego obrazu. Ważne aby pamiętać, że jedno repozytorium jest przeznaczone dla jednego konkretnego obrazu Docker. Oznacza, to tyle, że jeśli nasze rozwiązanie składa się z kilku obrazów Docker, to każdy z nich znajduje się osobnym repozytorium.

Stwórzmy pierwsze repozytorium o nazwie hello-api:

$: aws ecr create-repository --repository-name hello-api

Po wykonaniu polecenia otrzymujemy pierwsze informacje:

{
    "repository": {
        "repositoryArn": "arn:aws:ecr:eu-west-1:022084067179:repository/hello-api",
        "registryId": "022084067179",
        "repositoryName": "hello-api",
        "repositoryUri": "022084067179.dkr.ecr.eu-west-1.amazonaws.com/hello-api",
        "createdAt": 1578320155.0
    }
}

Ten dziwnie wyglądający numer 02208406717, to tzw. AWS Account ID i i jest ściśle związany z Twoim kontem AWS. Zawartość pola repositoryUri, można wykorzystać następnie do pobierania obrazu.

Aby uzyskać listę wszystkich dostępnych repozytoriów można posłużyć się poleceniem:

$: aws ecr describe-repositories

W moim przypadku wylistowane zostają dwa repozytoria w tym to, które przed chwilą utworzyłem:

{
     "repositories": [
        {
            "repositoryArn": "arn:aws:ecr:eu-west-1:022084067179:repository/hello-ui",
            "registryId": "022084067179",
            "repositoryName": "hello-ui",
            "repositoryUri": "022084067179.dkr.ecr.eu-west-1.amazonaws.com/hello-ui",
            "createdAt": 1557145046.0
        },
        {
            "repositoryArn": "arn:aws:ecr:eu-west-1:022084067179:repository/hello-api",
            "registryId": "022084067179",
            "repositoryName": "hello-api",
            "repositoryUri": "022084067179.dkr.ecr.eu-west-1.amazonaws.com/hello-api",
            "createdAt": 1578320155.0
        }
   ]
}

Uwierzytelnianie

Uwierzytelnienie do AWS za pomocą AWS CLI umożliwia jedynie zarządzanie usługami na naszym koncie – tworzenie, przeglądanie, modyfikacje. Aby móc wykonywać operacje związane z publikacją oraz pobieraniem obrazu z rejestru, musimy uwierzytelnić się w usłudze AWS ECR, tak aby klient Docker mógł bez problemowo komunikować się z rejestrem. Służy do tego polecenie:

$: $(aws ecr get-login --no-include-email)

Tyle wystarczy aby móc korzystać teraz z poleceń Dockera do publikacji i pobierania obrazów tj. docker pull czy docker push.

Uwierzytelnienie możliwe jest także za pomocą Docker Credential Helper. Możesz o tym poczytać więcej w artykule na blogu AWS, w tym artykule skupiamy się jedynie na podstawowej obsłudze ECR.

Publikacja obrazu w rejestrze

W przykładzie posłużyłem się przygotowaną już wcześniej aplikacją, którą wykorzystywałem w artykule na temat Dockera i AWS CloudWatch.

Zbudujmy najpierw obraz aplikacji:

$: docker build --tag hello-api:1.0.0 .

Lokalnie zbudowany obraz, musimy otagować prefixem złożonym z domeny naszego ECRa. Możemy także wykorzystać wartość z właściwości repositoryUri, zwróconej podczas tworzenia repozytorium.

$: docker tag hello-api:1.0.0 022084067179.dkr.ecr.eu-west-1.amazonaws.com/hello-api:1.0.0

Publikacja do rejestru ECR odbywa się za pomocą polecenia docker push. Wystarczy podać wcześniej utworzony tag, aby zbudowany lokalnie obraz aplikacji, został przesłany do rejestru.

$: docker push 022084067179.dkr.ecr.eu-west-1.amazonaws.com/hello-api:1.0.0

Sprawdzamy jak wygląda w rejestrze, wykonując polecenie:

$: aws ecr list-images --repository-name hello-api

Rezultatem jest lista wszystkich obrazów znajdujących się w zadanym repozytorium:

{
    "imageIds": [
        {
            "imageDigest": "sha256:e64fdf05d31008939c478d84665bd2d23519a4dd98a1e3d18f6747ae04d357ce",
            "imageTag": "1.0.0"
        }
    ]
}

Można także skorzystać z polecenia describe-images, które zwraca informacje na temat obrazów w bardziej rozbudowanej formie, podając m.in. rozmiar obrazu w bajtach.

$: aws ecr describe-images --repository-name hello-api

Wynik polecenia jest następujący:

{
    "imageDetails": [
        {
            "registryId": "022084067179",
            "repositoryName": "hello-api",
            "imageDigest": "sha256:e64fdf05d31008939c478d84665bd2d23519a4dd98a1e3d18f6747ae04d357ce",
            "imageTags": [
                "1.0.0"
            ],
            "imageSizeInBytes": 24349083,
            "imagePushedAt": 1578339891.0
        }
    ]
}

Wszystkie operacje przebiegły pomyślnie. Obraz został opublikowany w repozytorium.

Pobieranie obrazu z rejestru

Po prawidłowym uwierzytelnieniu w prywatnym rejestrze, nie pozostaje nam nic innego jak pobranie wymaganego obrazu. Wykorzystujemy polecenie docker pull, podając pełny adres rejestru oraz nazwę obrazu:

$: docker pull 022084067179.dkr.ecr.eu-west-1.amazonaws.com/hello-api:1.0.0

Pozostaje nam przetestować czy wszystko uruchamia się w sposób prawidłowy. W tym celu wystarczy wykonać polecenie run:

$: docker run -p 3000:3000 022084067179.dkr.ecr.eu-west-1.amazonaws.com/hello-api:1.0.0

Efektem jest uruchomienie kontenera w oparciu o obraz, znajdujący się w naszym prywatnym rejestrze Docker, utworzonym w ramach usługi AWS Elastic Container Registry:

> [email protected] start /usr/src/app
> node index.js

{"level":30,"time":1605467776097,"msg":"Server listening at http://0.0.0.0:3000","pid":21,"hostname":"0e16a3d0ea4f","v":1}
{"level":30,"time":1605467776098,"msg":"server listening on 3000","pid":21,"hostname":"0e16a3d0ea4f","v":1}

Udało się stworzyć obraz Dockerowy aplikacji, opublikować go w prywatnym rejestrze obrazów, a następnie uruchomić kontener w oparciu o opublikowany wcześniej obraz aplikacji. Można podsumować, że stworzyliśmy w tym momencie podstawowy proces wdrożeniowy – od tworzenia artefaktu w konkretnej wersji po uruchomienie działającej aplikacji.

Dodatkowe możliwości AWS ECR

Usługa AWS ECR oferuje także dodatkowe funkcjonalności, które sukcesywnie są dopracowywane. Moim zdaniem warto na pewno wspomnieć o:

  • Helm Chart  – ECR wspiera także publikację artefaktów Open Container Initiative (OCI), dlatego możliwa jest publikacja artefaktu w postaci Helm Chartu;
  • Lifecycle policies – Definicja cyklu życia obrazu. Za pomocą reguł można zdefiniować, kiedy dane obrazy mają zostać usunięte w sposób automatyczny z rejestru;
  • Image scanning – Obrazy w rejestrze, mogą być skanowane pod kątem wykrywania luk bezpieczeństwa w oprogramowaniu, które wykorzystywane jest w obrazie;
  • Tag immutability – Obrazy w rejestrze nie mogą być zmieniane. Oznacza to tyle, że otagowany obraz nie może zostać nadpisany.

ECR nie jest już tylko prostym repozytorium dla obrazów Docker. Zaczyna oferować coraz więcej dodatkowych funkcji, ułatwiających pracę z artefaktami w postaci Docker Image.

Podsumowanie

Jak wiele usług w AWS, ECR posiada, niewielki, darmowy plan. Przez okres roku, możemy zajmować 500MB przestrzeni w zupełności za darmo. Transfer miesięczny wychodzący, czyli w momencie pobierania obrazu poza zasoby AWSa jest darmowy do 1GB miesięcznie. Powyżej tej ilości musimy się zmierzyć z kwotą do 0.09 USD za 1GB (tanieje wraz z ilością wykorzystywanego transferu). Natomiast przestrzeń to 0.10 USD za każdy gigabajt.

Dzięki ECR w szybki sposób możemy utworzyć repozytorium dla swoich prywatnych obrazów. Jako, że jest to usługa AWS, łatwo integruje się z wieloma innymi usługami tej chmury publicznej. Dodatkowe funkcjonalności pomagają automatyzować procesy – cykl życia obrazu czy skanowanie pod kątem zapewnienia bezpieczeństwa w obrazie.

Z tymi przyjemnościami wiążą się jednak pewne opłaty, które z mojej perspektywy, utrzymywania kilku projektów (przez ostatnie 2 lata, kilkudziesięciu różnych obrazów), nie są wygórowane. ECR jest warty swojej ceny, ale także, na pewno wypróbowania w dobie konteneryzacji i chmury.

Na co dzień programujący CTO w Emphie Solutions. Projektuje, tworzy oraz wdraża rozwiązania oparte o ekosystem JavaScript. Rozwija swoje umiejętności z zakresu Cloud / DevOps / SRE. Fascynat programowania, architektury, chmury i dobrych praktyk w szerokim ujęciu. Na temat technologii publikuje materiały w ramach projektu DevEnv, którego jest założycielem.
PODZIEL SIĘ