Docker Hub作為Docker官方鏡像倉庫,提供了大量Docker鏡像的托管服務。但使用它來托管企業私有Docker鏡像存在一些問題,比如:
Docker Hub托管私有鏡像的服務目前只面對收費賬戶;
使用Docker Hub托管私有鏡像并不適合一些特殊場景,比如工作環境網絡是內網,不允許訪問外網,那就更不可能到Docker Hub去下載鏡像。
在這種情況下,如果能構建一個安全可靠的Docker私有庫,將會是一個更好的選擇。本文將介紹在AWS ECS基礎上結合AWS Elastic LoadBalancer、AWS Autoscaling Group、AWS S3及Docker官方提供的Registry鏡像構建安全、高可用的Docker私有庫的方案,幫助您輕構實現這一需求。
2.方案詳解
我們會使用AWS CloudFormation服務,使用自定義的模板腳本聲明所需的資源,實現自動化構建。接下來結合我們的模板腳本對本方案進行詳細介紹。
注意:以下內容與代碼相關部分只貼出主要代碼,部分代碼用…表示省略;完整模板代碼地址:
https://s3-us-west-2.amazonaws.com/blog.leonli.org/registry.yml
2.1 架構圖
根據以上架構圖,基本數據傳輸過程為:
1)Docker客戶端向鏡像倉庫發送的pull/push等命令事實上都是通過Docker dDaemon轉換成Restful請求的形式再發送給鏡像倉庫的。在本架構中,我們利用AWS Elastic LoadBalancer(簡稱ELB)接收客戶端發來的請求,作為整個架構的接入層。由于我們要求數據是通過TLS加密傳輸的,所以我們需要使用AWS IAM中的Server Certificate(由AWS IAM賬戶上傳的TLS證書)與ELB關聯,實現對客戶端發來的請求進行加密。
2)ELB會將請求反向代理給后端分布在不同可用區的兩臺Container Instance(安裝了Docker運行環境的EC2實例),Container Instance中運行了Docker Registry服務。當請求到達Registry時,我們需要首先使用內置在Registry中的用戶認證文件(比如本架構中使用Apache Htpasswd創建的基本用戶名密碼保護文件),進行用戶認證,認證不通過,則駁回請求,認證通過,才可以讀寫數據。
3)將數據統一存儲在一個只供創建者使用的S3 Bucket中。
2.2 基于AWS ECS運行Docker Registry服務
Amazon EC2 Container Service (ECS) 是一項高度可擴展的高性能容器管理服務,它讓您能夠在托管的 Amazon EC2 實例群集上輕松運行Docker應用程序。 Amazon ECS主要有以下幾個組件:ECS Cluster、 Container Instance、Task、ECS Service。這里基于ECS運行了Docker Registry服務,架構如下:
(1)首先在模板中定義了一個ECS Cluster,用來管理相關的Container Instance。ECS提供了ECS-Optimize AMI來創建EC2實例作為Container Instance,ECS-Optimize AMI已經內置Docker運行環境和Container Agent代理,可以為我們節省安裝這些環境所需的時間。
Container Instance在啟動時可以由Container Agent根據配置文件/etc/ecs/ecs.config中的ClusterName屬性的值知道需要將實例注冊到哪個ECS Cluster上。
因為我們要使用Auto Scaling服務實現對EC2實例的伸縮控制。所以我們使用Auto Scaling的Launch Config組件聲明我們的Container Instance。并通過UserData傳入Shell腳本,此腳本主要完成以下三件事:
調用 echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config ,將Container Instance注冊到我們的ECS Cluster中。
創建/docker-registry/certs目錄和/docker-registry/auth目錄,并調用aws s3 copy命令從指定的S3 Bucket中復制TLS證書文件和htpasswd用戶認證文件。這些文件將在運行Docker Registry時使用到。
調用cfn-signal命令,通知AutoScaling Group資源EC2實例已經啟動完畢。