推送 Docker 镜像到 Amazon ECR 仓库

Docker 镜像在未指定仓库时默认是从  Docker Hub 拉取的。如果需向 Docker Hub 推送镜像的话还可用 docker login 在交互中完成登陆 Docker Hub 的操作。docker login 的命令格式是

docker login [OPTIONS] [SERVER]
所以我们可以连接到任何的 Docker 镜像仓库,也可以是本机,但我们这里所要介绍的是如何推送镜像到 AWS 给我们提供的 Docker 镜像仓库(Amazon ECR - Amazon Elastic Container Registry)。每个帐号下都有自己独立的仓库,镜像推送到了  Amazon ECR 后我们能够很方便的在 ECS, Batch 服务中使用它,也可以从 ECR 拉取镜像到本地来。

首先我们来做一个运行 Spring Boot Web 的简单的 Docker 镜像,假定已用 mvc pacakge 生成了一个可独立运行的 jar 包 java-webapp-0.0.1-SNAPSHOT.jar 。该应用开启一个 Web 服务,访问 http://localhost:8080 显示一行字符串 Hello World!

创建一个目录 aws-docker, 并把 java-webapp-0.0.1-SNAPSHOT.jar 移入该目录,在其下创建 Dockerfile 文件,文件目录结构如下:
aws-docker
  ├── Dockerfile
  └── java-webapp-0.0.1-SNAPSHOT.jar
Dockerfile 的内容是
1FROM openjdk:8-jre-slim
2ADD java-webapp-0.0.1-SNAPSHOT.jar app.jar
3
4EXPOSE 8080
5
6ENTRYPOINT [ "java", "-jar", "/app.jar" ]

 然后是确保本地安装了 docker 和 aws-cli. 本人在本地已生成了 ~/.aws/credentials 文件用于 aws 命令的用户验证,为简单起见,profile 是 default

有了以上的前提之后,正式步入创建 Docker 镜像,登陆 Amazon ECR, 推送镜像到 ECR,从 ECR 拉取 Docker 的操作。

创建镜像和 Tag

基于前面的 Dockerfile 创建一个  Docker 镜像,如果要把该镜像推送到 ECR 必须有一符合规格的 Tag 名称。命令行中来到与 aws-docker 平行的目录,我们可以执行下面任意一组命令
docker build -t java-webapp:latest ./aws-docker
docker tag java-webapp:latest aws_account_id.dkr.ecr.us-east-1.amazonaws.com/java-webapp:latest

docker build -t aws_account_id.dkr.ecr.us-east-1.amazonaws.com/java-webapp:latest
aws_account_id 是当前登陆帐号的 ID, 可以在网页登陆 AWS 后的  Account Settings 中找到,也可以在 ~/.aws/credentials 文件(如果有的话)中找到,也可以在后面介绍的 aws ecr get-login 命令中看到。

总之,待推送的镜像必须符合 aws_account_id.dkr.ecr.us-east-1.amazonaws.com/java-webapp:latest 规则, 即 RepositoryURI:tag, 其中的 java-webapp 是仓库名,接下来用 docker push 才知道往哪儿推。

登陆 Amazon ECR

在推送镜像到 ECR 之前类似于登陆 Docker Hub 一样,也必须事先登陆到 Amazon ECR,命令 aws ecr get-login --no-include-email 为我们生成一个完整的 docker login 命令,大致如下:
docker login -u AWS -p eyJwYXlsb2FkIjoi.......== https://aws_account_id.dkr.ecr.us-east-1.amazonaws.com
执行上面的 docker login 命令将完成登陆 ECR 的过程,生成的令牌在 12 小时有效。

借助于 Shell 的管道,可以用一条简短的命令完成以上两步,即
aws ecr get-login --no-include-email | sh
注:对于 Docker 17.06 或更高的版本,需要 --no-include-email 参数

创建 Amazon ECR 仓库

莫急,在执行 docker push 之前还需要提前创建好 java-webapp 仓库,否则在推送的时候会出现找不到 repository 的错误
name unkown: The repository with name 'java-webapp' does not exist in the registry with id 'xxxxxxxxxxxx'
根据每个人的所好,在 Web 控制台或是命令行下创建仓库都可以,我这里就不妨命令行一路到底,用  aws 命令
aws ecr create-repository --repository-name java-webapp
注意:仓库名必须要保持一致

推送 Docker 镜像到 ECR

现在可是万事俱备,什么风也不歉了。只要像推送镜像到  Docker Hub 那样操作就行了
docker push aws_account_id.dkr.ecr.us-east-1.amazonaws.com/java-webapp:latest ➜ / docker push xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/java-webapp:latest
The push refers to repository [xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/java-webapp]
ee923fd81c63: Layer already exists
bca5421261df: Layer already exists
473adefcdec2: Layer already exists
7f877179d500: Layer already exists
9c0da68f893b: Layer already exists
e01103f88b34: Layer already exists
2ec5c0a4cb57: Layer already exists
latest: digest: sha256:bb95bc9f6ca4f54b4ef23ae6b3b6b1793d04397c5066bc3ce3891d8d2dc86ec0 size: 1787

从 ECR 拉取镜像到本地运行

一个镜像就这么上传到了 Amazon ECR  了,我们能够在 ECS 或 Batch 服务中使用它了。既然能从本地 push 到 ECR, 也就无法阻挡从 ECR 拉取镜像到本地运行。假设已用 docker rmi <image_id> 删除了本地的 java-webapp 镜像。

 1➜ / docker run -p 8080:8080 xxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/java-webapp
 2Unable to find image 'xxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/java-webapp:latest' locally
 3latest: Pulling from java-webapp
 4e7bb522d92ff: Already exists
 5acf3a7df1b51: Already exists
 6c1c98005fcff: Already exists
 739dcc90226db: Already exists
 8693e7ee43844: Already exists
 9cb083d9c54cf: Already exists
1046f48bdb2c6e: Already exists
11Digest: sha256:bb95bc9f6ca4f54b4ef23ae6b3b6b1793d04397c5066bc3ce3891d8d2dc86ec0
12Status: Downloaded newer image for xxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/java-webapp:latest<br/><br/>
13  .   ____          _            __ _ _
14 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
15( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
16 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
17  '  |____| .__|_| |_|_| |_\__, | / / / /
18 =========|_|==============|___/=/_/_/_/
19 :: Spring Boot ::        (v1.5.9.RELEASE)

反正前面用 aws ecr get-login | sh 之后,docker 就是知道根据镜像名找到匹配的仓库(Docker Hub 或 Amazon ECR) 去下载。

测试:
➜ / curl http://localhost:8080
Hello World!

终极图片

在 Amazon ECR 的控制台 https://console.aws.amazon.com/ecs/home?region=us-east-1#/repositories, 选择到刚刚 Push 上去的  java-webapp,点击 View Push Commands 按钮可以看到前面所有

  1. aws ecr get-login
  2. docker build
  3. docker tag
  4. docker push

命令,见图:

注意:前面的命令都假定了使用 ~/.aws/credentials 或 ~/.aws/config 中配置的默认区域 us-east-1, 如果要切换到其他的区域请在命令行参数中指定,此时仓库的 URI 也会有所变化。 永久链接 https://yanbin.blog/push-docker-image-to-amazon-ecr-repository/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。