Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow support of Docker registry version 2. #9

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM nginx:1.12.0-alpine
FROM nginx:1.17.7-alpine

RUN apk -v --update add \
python \
Expand All @@ -8,12 +8,9 @@ RUN apk -v --update add \
apk -v --purge del py-pip && \
rm /var/cache/apk/*

ADD configs/nginx/nginx.conf /etc/nginx/nginx.conf
ADD configs/nginx/ssl /etc/nginx/ssl

ADD configs/entrypoint.sh /entrypoint.sh
ADD configs/auth_update.sh /auth_update.sh
ADD configs/renew_token.sh /renew_token.sh
ADD configs/nginx/*.conf /etc/nginx/
ADD configs/*.sh /

EXPOSE 80 443

Expand Down
78 changes: 56 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@ Based on official nginx alpine.

[Docker image repository](https://hub.docker.com/r/catalinpan/aws-ecr-proxy/)

The container will renew the aws token every 6 hours.
The container will renew the AWS token every 6 hours.

Variables:
```
AWS_KEY
AWS_SECRET
REGION
RENEW_TOKEN - default 6h
REGISTRY_ID - optional, used for cross account access
```
### Variables

The following table describes the parameters you can provide as Docker environment variables.

### Health check
| Name | Default value | Description |
|---------------------------|---------------|-----------------------------------------------------------------|
| `AWS_KEY` | | The AWS access key used to execute AWS ECR API requests. |
| `AWS_SECRET` | | The AWS secret used to execute AWS ECR API requests. |
| `DOCKER_REGISTRY_VERSION` | 2 | The version of the Docker registry to use. |
| `REGION` | | The AWS region where your AWS ECR registries are located. |
| `RENEW_TOKEN` | 6h | The interval used to indicate how often to renew the AWS token. |
| `REGISTRY_ID` | | Used for cross account access. |

To check the health of the container/registry use ```FQDN/ping``` which will give you the heath of the registry with the correct status code.

### Health check

To check the health of the container/registry use `FQDN/ping` which will give you the heath of the registry with the correct status code.

### AWS instance with IAM role

Expand All @@ -31,9 +36,11 @@ The configs will be checked in the following order:
- variables declared at run time
- IAM role

If none are found the container will not start. Check the logs with ```docker logs CONTAINER_ID```
If none are found the container will not start. Check the logs with `docker logs CONTAINER_ID`.

## Docker

## Docker run:
### Run
##### Without ssl
This will require either to add insecure registry URL or a load balancer with valid ssl certificates.
Check https://docs.docker.com/registry/insecure/ for more details.
Expand All @@ -53,33 +60,60 @@ docker run -e AWS_SECRET='YOUR_AWS_SECRET' \
-d catalinpan/aws-ecr-proxy
```
##### With a valid AWS CLI configuration file
The configuration should look like below example.
The configuration should look like below example.
```
cat ~/.aws/config
```
```
[default]
# region example eu-west-1
region = REGION
region = REGION
aws_access_key_id = YOUR_AWS_KEY
aws_secret_access_key = YOUR_AWS_SECRET
```
```
docker run -v ~/.aws:/root/.aws:ro
-v `pwd`/YOUR_CERTIFICATE.key:/etc/nginx/ssl/default.key:ro \
-v `pwd`/YOUR_CERTIFICATE.crt:/etc/nginx/ssl/default.crt:ro \
-d catalinpan/aws-ecr-proxy
docker run -v ~/.aws:/root/.aws:ro \
-v `pwd`/YOUR_CERTIFICATE.key:/etc/nginx/ssl/default.key:ro \
-v `pwd`/YOUR_CERTIFICATE.crt:/etc/nginx/ssl/default.crt:ro \
-d catalinpan/aws-ecr-proxy
```
##### IAM role configured
with region and credentials from IAM role
With region and credentials from IAM role.
```
docker run -d catalinpan/aws-ecr-proxy
```
with region as environment variable and credentials from IAM role
With region as environment variable and credentials from IAM role.
```
docker run -e REGION='YOUR_AWS_REGION' -d catalinpan/aws-ecr-proxy
```

##### With an explicit Docker registry version
```
docker run -d catalinpan/aws-ecr-proxy \
-e DOCKER_REGISTRY_VERSION=1
```

### Build
Build the default `catalinpan/aws-ecr-proxy` image with the version specified in the `version.txt` file.
```
./build.sh
```
Build an image with a custom name and version.
```
./build.sh --name=company-name/aws-ecr-proxy --version=1.0.0
```

### Publish
Publish the default `catalinpan/aws-ecr-proxy` image with the version specified in the `version.txt` file.
```
./publish.sh --latest
```
Publish an image with a custom name and version.
```
./publish.sh --latest --name=company-name/aws-ecr-proxy --version=1.0.0
```


## SSL
The certificates included are just to get nginx started. Generate your own certificate, get valid ssl certificates or use the container behind a load balancer with valid SSL certificates.

Expand All @@ -97,4 +131,4 @@ The configs can be changed to get aws_config and ssl certificates as secrets.
The configuration provided will require valid ssl certificates or to be behind a load balancer with valid ssl.

#### DaemonSet
The daemonSet will be available on all the nodes. Deployments can use ```127.0.0.1:5000/container_name:tag``` instead of ```FQDN/container_name:tag```
The daemonSet will be available on all the nodes. Deployments can use `127.0.0.1:5000/container_name:tag` instead of `FQDN/container_name:tag`.
43 changes: 43 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/sh

usage () {
printf "NAME\n"
printf " build.sh -- build a new Docker image.\n"
printf "SYNOPSIS\n"
printf " build.sh [options]\n"
printf "DESCRIPTION\n"
printf " build.sh is a tool to build a new Docker image.\n"
printf "OPTIONS\n"
printf " -h, --help\n"
printf " Usage help. This lists all current command line options with a short description.\n"
printf " --name=<value>\n"
printf " The name of the Docker image to build, default to 'catalinpan/aws-ecr-proxy'.\n"
printf " --version\n"
printf " The version of the Docker image to build, default to the content of 'version.txt'.\n"
}

NAME=catalinpan/aws-ecr-proxy
VERSION=$(cat version.txt)

while [ $# -gt 0 ]
do
case $1 in
-h | --help)
usage
exit
;;
--name=*)
NAME=${1#*=}
;;
--version=*)
VERSION=${1#*=}
;;
*)
usage
exit
;;
esac
shift
done

docker build --no-cache --pull -t "${NAME}:${VERSION}" .
4 changes: 2 additions & 2 deletions configs/auth_update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ if [ "$REGISTRY_ID" = "" ]
then
token=$(aws ecr get-login --no-include-email | awk '{print $6}')
else
token=$(aws ecr get-login --no-include-email --registry-ids $REGISTRY_ID | awk '{print $6}')
token=$(aws ecr get-login --no-include-email --registry-ids "${REGISTRY_ID}" | awk '{print $6}')
fi
auth_n=$(echo AWS:${token} | base64 |tr -d "[:space:]")
auth_n=$(echo "AWS:${token}" | base64 |tr -d "[:space:]")

sed -i "s|${auth%??}|${auth_n}|g" ${nx_conf}
41 changes: 30 additions & 11 deletions configs/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ header_config() {
echo "[default]" > /root/.aws/config
}
region_config() {
echo "region = $@" >> /root/.aws/config
echo "region = $*" >> /root/.aws/config
}

test_iam() {
wget -q -O- ${AWS_IAM} | grep -q 'region'
}

test_config() {
grep -qrni $@ ${AWS_FOLDER}
grep -qrni "$@" ${AWS_FOLDER}
}

fix_perm() {
Expand All @@ -30,18 +30,18 @@ if test_config region
then
echo "region found in ~/.aws mounted as secret"
# configure regions if variable specified at run time
elif [[ "$REGION" != "" ]]
elif [ "$REGION" != "" ]
then
header_config
region_config $REGION
region_config "${REGION}"
fix_perm
# check if the region can be pulled from AWS IAM
elif test_iam
then
echo "region detected from iam"
REGION=$(wget -q -O- ${AWS_IAM} | grep 'region' |cut -d'"' -f4)
header_config
region_config $REGION
region_config "${REGION}"
fix_perm
else
echo "No region detected"
Expand All @@ -53,7 +53,7 @@ if test_config aws_access_key_id
then
echo "aws key and secret found in ~/.aws mounted as secrets"
# if both key and secret are declared
elif [[ "$AWS_KEY" != "" && "$AWS_SECRET" != "" ]]
elif [ "$AWS_KEY" != "" ] && [ "$AWS_SECRET" != "" ]
then
echo "aws_access_key_id = $AWS_KEY
aws_secret_access_key = $AWS_SECRET" >> ${AWS_FOLDER}/config
Expand All @@ -70,20 +70,39 @@ else
fi
fi

# Check the Docker registry version to use
if [ -z "${DOCKER_REGISTRY_VERSION}" ]
then
DOCKER_REGISTRY_VERSION=2
elif [ "${DOCKER_REGISTRY_VERSION}" != "1" ] && [ "${DOCKER_REGISTRY_VERSION}" != "2" ]
then
echo "Docker registry version ${DOCKER_REGISTRY_VERSION} is invalid !"
exit 1
fi

# Pick the right NGinx configuration file
echo "Docker registry version is ${DOCKER_REGISTRY_VERSION}"
cat /etc/nginx/nginx-docker-registry-v${DOCKER_REGISTRY_VERSION}.conf > ${nx_conf}

# update the auth token
if [ "$REGISTRY_ID" = "" ]
then
then
aws_cli_exec=$(aws ecr get-login --no-include-email)
else
aws_cli_exec=$(aws ecr get-login --no-include-email --registry-ids $REGISTRY_ID)
aws_cli_exec=$(aws ecr get-login --no-include-email --registry-ids "${REGISTRY_ID}")
fi
auth=$(grep X-Forwarded-User ${nx_conf} | awk '{print $4}'| uniq|tr -d "\n\r")
token=$(echo "${aws_cli_exec}" | awk '{print $6}')
auth_n=$(echo AWS:${token} | base64 |tr -d "[:space:]")
auth_n=$(echo "AWS:${token}" | base64 |tr -d "[:space:]")
reg_url=$(echo "${aws_cli_exec}" | awk '{print $7}')

sed -i "s|${auth%??}|${auth_n}|g" ${nx_conf}
sed -i "s|REGISTRY_URL|$reg_url|g" ${nx_conf}
# We use a '.new' file to prevent errors like this one.
# 'sed: can't move '/etc/nginx/nginx.confhgFhDa' to '/etc/nginx/nginx.conf': Resource busy'
cp ${nx_conf} ${nx_conf}.new
sed -i "s|${auth%??}|${auth_n}|g" ${nx_conf}.new
sed -i "s|REGISTRY_URL|$reg_url|g" ${nx_conf}.new
echo "" > ${nx_conf}
cat ${nx_conf}.new > ${nx_conf}

/renew_token.sh &

Expand Down
File renamed without changes.
60 changes: 60 additions & 0 deletions configs/nginx/nginx-docker-registry-v2.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
events {
worker_connections 4096;
}

http {
resolver 8.8.8.8 8.8.4.4;

server {

listen 80 default_server;
server_name _;

location /v2/ {
set $upstream REGISTRY_URL;

proxy_pass $upstream;
proxy_redirect $upstream http://$host;

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-User "Basic $http_authorization";
proxy_set_header Authorization "Basic $http_authorization";

proxy_pass_header Server;

client_max_body_size 0;
proxy_connect_timeout 300s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
send_timeout 300s;
}
}

server {
listen 443 ssl;
server_name _;
ssl_certificate /etc/nginx/ssl/default.crt;
ssl_certificate_key /etc/nginx/ssl/default.key;

location /v2/ {
set $upstream REGISTRY_URL;

proxy_pass $upstream;
proxy_redirect $upstream https://$host;

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-User "Basic $http_authorization";
proxy_set_header Authorization "Basic $http_authorization";

proxy_pass_header Server;

client_max_body_size 0;
proxy_connect_timeout 300s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
send_timeout 300s;
}
}
}
2 changes: 1 addition & 1 deletion configs/renew_token.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh

while sleep ${RENEW_TOKEN:-6h}
while sleep "${RENEW_TOKEN:-6h}"
do
/auth_update.sh
nginx -s reload
Expand Down
Loading