Коммит
e7ed46cbbd
26
README.md
26
README.md
|
@ -2,30 +2,36 @@
|
|||
|
||||
This repo contains Samples and Troubleshooting tips for Azure Container Registry. If you face any issues, Please log it here - https://github.com/Azure/acr/issues
|
||||
|
||||
[FAQ] (docs/FAQ.md)
|
||||
[FAQ](docs/FAQ.md)
|
||||
|
||||
[CLI Troubleshooting] (docs/CLI - Troubleshooting Guide .md)
|
||||
|
||||
[Moving Repositories] (docs/move-repositories-to-new-registry.md)
|
||||
[Troubleshooting](docs/Troubleshooting%20Guide.md)
|
||||
|
||||
## Blogs
|
||||
ACR User Accounts - https://blogs.msdn.microsoft.com/stevelasker/2016/11/17/azure-container-registry-user-accounts/
|
||||
|
||||
|
||||
## Resources
|
||||
|
||||
Official Documentation Page - https://docs.microsoft.com/en-us/azure/container-registry/
|
||||
|
||||
Contribute to Documentation - https://github.com/Microsoft/azure-docs/blob/master/articles/container-registry/toc.md
|
||||
Contribute to Documentation - https://github.com/Microsoft/azure-docs/blob/master/articles/container-registry/TOC.md
|
||||
|
||||
Azure Container Registry Home Page - https://azure.microsoft.com/en-us/services/container-registry/
|
||||
|
||||
Azure Management Portal - https://portal.azure.com/#blade/HubsExtension/Resources/resourceType/Microsoft.ContainerRegistry%2Fregistries
|
||||
|
||||
AZ CLI Reference - https://github.com/Azure/azure-cli/blob/master/src/command_modules/azure-cli-acr/README.rst
|
||||
AZ CLI Reference - https://docs.microsoft.com/en-us/cli/azure/acr
|
||||
|
||||
REST API Reference - https://docs.microsoft.com/en-us/rest/api/containerregistry/
|
||||
|
||||
Python SDK - https://github.com/Azure/azure-sdk-for-python/tree/master/azure-mgmt-containerregistry
|
||||
Azure PowerShell Reference - https://docs.microsoft.com/powershell/module/azurerm.containerregistry
|
||||
|
||||
Log Issues - https://github.com/Azure/acr/issues
|
||||
|
||||
## API and SDK References
|
||||
|
||||
REST API Reference - https://docs.microsoft.com/en-us/rest/api/containerregistry/
|
||||
> Swagger Specification - https://github.com/Azure/azure-rest-api-specs/blob/master/arm-containerregistry/2017-03-01/swagger/containerregistry.json
|
||||
|
||||
SDK for Python - https://pypi.python.org/pypi/azure-mgmt-containerregistry
|
||||
> Source - https://github.com/Azure/azure-sdk-for-python/tree/master/azure-mgmt-containerregistry
|
||||
|
||||
SDK for .NET - https://www.nuget.org/packages/Microsoft.Azure.Management.ContainerRegistry
|
||||
> Source - https://github.com/Azure/azure-sdk-for-net/tree/AutoRest/src/ResourceManagement/ContainerRegistry
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
# Azure Container Registry integration with Azure Active Directory
|
||||
|
||||
The Azure Container Registry allows users to manage a private Docker registry on the cloud. Our service enables customers to store and manage container images across all types of Azure deployments, keep container images near deployments to reduce latency and costs, maintain Windows and Linux container images in a single Docker registry, use familiar, open-source Docker command line interface (CLI) tools, and simplify registry access management with Azure Active Directory.
|
||||
|
||||
The integration of Azure Container Registry with Azure Active Directory is crucial in order to enable transparent authentication and authorization of users and headless services using AAD credentials. In this scenario, a user will only have to use their AAD credentials to log-in to their private registry, and the Azure Container Service will take care of the authorization validation of each operation using the provided credentials.
|
||||
|
||||
Under the hood Azure Container Service utilizes the [oauth2](https://oauth.net/2/) authorization protocol, as described by the [Docker Registry v2 authentication via central service documentation](https://docs.docker.com/registry/spec/auth/token/) as well as the [Docker Registry v2 Bearer token specification](https://docs.docker.com/registry/spec/auth/jwt/). The JWT tokens generated by the Azure Container Registry are easy to observe in [jwt.io](https://jwt.io/).
|
||||
|
||||
## Authenticating to a registry with Azure CLI
|
||||
|
||||
The process to log in to the registry, from the user's perspective, is simple. The user will use the Microsoft Azure CLI 2.0:
|
||||
```
|
||||
az acr login -n contosoregistry
|
||||
```
|
||||
|
||||
Internally, the CLI will follow these steps:
|
||||
1. Calls to Azure Resource Manager to resolve the login server for the specified registry.
|
||||
2. Obtains refresh credentials from the profile in use. For a headless call, this will give you the registered SPN, for a regular user this will give you a refresh token.
|
||||
3. Makes an HTTPS GET call to the registry server's `/v2` endpoint, without credentials. A bearer token authentication challenge is expected, specifying realm and service values. The realm contains the authentication server's URL.
|
||||
4. Makes an HTTPS POST call to the authentication server's `POST /oauth2/exchange` endpoint, with a body indicating the grant type, the service, the tenant, and the credentials.
|
||||
5. From the server's response, we extract an Azure Container Registry refresh token.
|
||||
6. Pass the refresh token as the password to the Docker CLI, using a null GUID as the username and calling `docker login`. From here on, the docker CLI takes care of the authorization cycle using oauth2.
|
||||
|
||||
At the end Docker will store the refresh token and go through the oauth2 flow on each operation it does against the Azure Container Registry.
|
||||
|
||||
## Listing a repository with Azure CLI
|
||||
|
||||
The Microsoft Azure CLI 2.0 allows users to also list the repositories registries, and list tags for a repository in a registry. Here's how users can achieve listing the repositories in a registry:
|
||||
```
|
||||
az acr repository list -n contosoregistry
|
||||
```
|
||||
|
||||
Internally, the CLI will follow these steps:
|
||||
1. Calls to Azure Resource Manager to resolve the login server for the specified registry.
|
||||
2. Obtains refresh credentials from the profile in use. For a headless call, this will give you the registered SPN, for a regular user this will give you a refresh token.
|
||||
3. Makes an HTTPS GET call to the registry server's `/v2` endpoint, without credentials. A bearer token authentication challenge is expected, specifying realm and service values. The realm contains the authentication server's URL.
|
||||
4. Makes an HTTPS POST call to the authentication server's `POST /oauth2/exchange` endpoint, with a body indicating the grant type, the service, the tenant, and the credentials.
|
||||
5. From the server's response we extract an Azure Container Registry refresh token.
|
||||
6. Makes an HTTPS POST call to the authentication server's `POST /oauth2/token` endpoint, with a body indicating the grant type, the service, the scope, and the Azure Container Registry refresh token.
|
||||
7. From the server's response we extract an Azure Container Registry access token.
|
||||
8. Makes an HTTPS GET call to the registry server's `GET /v2/_catalog` endpoint using the access token as the bearer token.
|
||||
9. Obtains the data from the service and displays it.
|
||||
|
||||
When listing the tags of a repository, every step above is the same except for the call to the endpoint that gives the tags which is `GET /v2/contosoregistry/tags/list` instead of `GET /v2/_catalog`.
|
||||
|
||||
# Azure Container Registry refresh tokens and access tokens
|
||||
|
||||
Let's follow an example call to list a repository:
|
||||
```
|
||||
az acr repository list -n contosoregistry
|
||||
```
|
||||
|
||||
This will produce a JWT refresh token with the following payload:
|
||||
```
|
||||
{
|
||||
"jti": "365e3b5b-844e-4a21-a38c-4d8aebdd6a06",
|
||||
"sub": "user@contoso.com"
|
||||
"nbf": 1497988712,
|
||||
"exp": 1497990801,
|
||||
"iat": 1497988712,
|
||||
"iss": "Azure Container Registry",
|
||||
"aud": "contosoregistry.azurecr.io",
|
||||
"version": "1.0",
|
||||
"grant_type": "access_token_refresh_token",
|
||||
"tenant": "409520d4-8100-4d1d-ad47-72432ddcc120",
|
||||
"credential": "AQA...iAA"
|
||||
"permissions": {
|
||||
"actions": [
|
||||
"*"
|
||||
],
|
||||
"notActions": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Followed by an access token with the following payload:
|
||||
```
|
||||
{
|
||||
"jti": "ec425c1e-7eda-4f70-adb5-19f927e34a41",
|
||||
"sub": "user@contoso.com"
|
||||
"nbf": 1497988907,
|
||||
"exp": 1497993407,
|
||||
"iat": 1497988907,
|
||||
"iss": "Azure Container Registry",
|
||||
"aud": "contosoregistry.azurecr.io",
|
||||
"access": [
|
||||
{
|
||||
"type": "registry",
|
||||
"name": "catalog",
|
||||
"actions": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
# Getting credentials programatically
|
||||
|
||||
In order to sign in to a container you'll need to exchange AAD credentials for ACR credentials. The accepted form of credential exchange are:
|
||||
- AAD access token.
|
||||
- AAD refresh token.
|
||||
- AAD access token and refresh token.
|
||||
|
||||
Ideally you'll present both the AAD access token and the AAD refresh token. The AAD access token is used to talk to the Azure Resource Manager and query for the set of permissions that the user has for the container registry resource. The AAD refresh token is used in two ways:
|
||||
1. If no AAD access token was presented, the AAD refresh token is used to obtain an AAD access token.
|
||||
2. The AAD refresh token is sent back to the user so they can initiate a token refresh cycle against AAD. If no AAD refresh token is sent, then the client won't have this credential at hand to initiate a credential refresh.
|
||||
|
||||
The cycle to get credentials looks as follows:
|
||||
1. Call `POST /oauth2/exchange` presenting the AAD refresh token and the AAD access token. The service will return you an ACR refresh token.
|
||||
2. Call `POST /oauth2/token` presenting the ACR refresh token. The service will return you an ACR access token which you can use to call the Azure Container Registry's APIs.
|
||||
|
||||
## Calling `POST /oauth2/exchange` to get an ACR refresh token
|
||||
|
||||
In this example, we'll try to obtain an ACR refresh token from existing AAD tokens. Assume you have the following:
|
||||
1. A valid container registry, which here we'll call `contosoregistry.azurecr.io`.
|
||||
2. The AAD tenant identifier associated to the credentials, which here we'll take to be `409520d4-8100-4d1d-ad47-72432ddcc120`.
|
||||
3. Valid AAD access token and AAD refresh token credentials with access to the aforementioned container registry.
|
||||
|
||||
The AAD access token and AAD refresh token can be obtained from the Azure CLI. After running `az login` check file `$HOME/.azure/accessTokens.json` (`%HOMEDRIVE%%HOMEPATH%\.azure\accessTokens.json` in Windows) for the token values.
|
||||
|
||||
We'll now call `POST /oauth2/exchange` to exchange the AAD tokens for an ACR refresh token. Here's how such a call looks when done via `curl`:
|
||||
```bash
|
||||
export registry="contosoregistry.azurecr.io"
|
||||
export tenant="409520d4-8100-4d1d-ad47-72432ddcc120"
|
||||
export aad_refresh_token="AQA...iAA"
|
||||
export aad_access_token="eyJ...H-g"
|
||||
curl -v -X POST -H "Content-Type: application/x-www-form-urlencoded" -d \
|
||||
"grant_type=access_token_refresh_token&service=$registry&tenant=$tenant&refresh_token=$aad_refresh_token&access_token=$aad_access_token" \
|
||||
https://$registry/oauth2/exchange
|
||||
```
|
||||
|
||||
The body of the POST message is a querystring-like text that specifies the following values:
|
||||
- `grant_type`, which can take a value of `access_token_refresh_token`, or `access_token`, or `refresh_token`.
|
||||
- `service`, which must indicate the name of your Azure container registry.
|
||||
- `tenant`, which is the AAD tenant associated to the AAD credentials.
|
||||
- `refresh_token`, the AAD refresh token, mandatory when `grant_type` is `access_token_refresh_token` or `refresh_token`.
|
||||
- `access_token`, the AAD access token, mandatory when `grant_type` is `access_token_refresh_token` or `access_token`.
|
||||
|
||||
The outcome of this operation will be a response with status 200 OK and a body with the following JSON payload:
|
||||
```json
|
||||
{"refresh_token":"eyJ...L7a"}
|
||||
```
|
||||
This response is the ACR refresh token which you can inspect with [jwt.io](https://jwt.io/). You can now use it to obtain an ACR access token programmatically or simply send it to the `docker login` command to get docker talking to the Azure Container Registry.
|
||||
|
||||
## Authenticating docker with an ACR refresh token
|
||||
|
||||
Once you have obtained an ACR refresh token, you can use the docker CLI to sign in to your registry like this:
|
||||
```bash
|
||||
export registry="contosoregistry.azurecr.io"
|
||||
export acr_username="00000000-0000-0000-0000-000000000000"
|
||||
export acr_refresh_token="eyJ...L7a"
|
||||
docker login -u "$acr_username" -p "$acr_refresh_token" $registry
|
||||
```
|
||||
|
||||
The null GUID tells the container registry that this is an ACR refresh token during the login flow. Once the authentication succeeds you can talk to the Azure Container Registry with commands like `docker pull` and `docker push`. For example:
|
||||
|
||||
```bash
|
||||
docker pull contosoregistry.azurecr.io/contoso-marketing
|
||||
```
|
||||
|
||||
Notice that the ACR refresh token will be saved by the docker CLI in its credential store, and will be used by the docker CLI to obtain an ACR access token on each operation it performs against the Azure Container Registry. The ACR refresh token is made so it stops working after a period of time, but if you obtained it using either `grant_type=access_token_refresh_token` or `grant_type=refresh_token` then it can be refreshed automatically by installing the [ACR docker credential helper](https://github.com/azure/acr-docker-credential-helper).
|
||||
|
||||
## Calling `POST /oauth2/token` to get an ACR access token
|
||||
|
||||
In this example, we'll try to obtain an ACR access token from existing ACR refresh token, and this access token will only work for the operation we're trying to perform, which is a call to the `GET /v2/_catalog` API. Assume you have the following:
|
||||
1. A valid container registry, which here we'll call `contosoregistry.azurecr.io`.
|
||||
2. A valid ACR refresh token.
|
||||
|
||||
The first thing you want is to obtain an authentication challenge for the operation you want to on the Azure Container Registry. That can be done by targetting the API you want to call without any authentication. Here's how to do that via `curl`:
|
||||
```bash
|
||||
export registry="contosoregistry.azurecr.io"
|
||||
curl -v https://$registry/v2/_catalog
|
||||
```
|
||||
Note that `curl` by default does the request as a `GET` unless you specify a different verb with the `-X` modifier.
|
||||
|
||||
This will output the following payload, with `...` used to shorten it for illustrative purposes:
|
||||
|
||||
```
|
||||
< HTTP/1.1 401 Unauthorized
|
||||
...
|
||||
< Www-Authenticate: Bearer realm="https://contosoregistry.azurecr.io/oauth2/token",service="contosoregistry.azurecr.io",scope="registry:catalog:*"
|
||||
...
|
||||
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]}
|
||||
```
|
||||
|
||||
Notice the response payload has a header called `Www-Authenticate` that gives us the following information:
|
||||
- The type of challenge: `Bearer`.
|
||||
- The realm of the challenge: `https://contosoregistry.azurecr.io/oauth2/token`.
|
||||
- The service of the challenge: `contosoregistry.azurecr.io`.
|
||||
- The scope of the challenge: `registry:catalog:*`.
|
||||
|
||||
The body of the payload might provide additional details, but all the information you need is contained in the `Www-Authenticate` header.
|
||||
|
||||
With this information we're now ready to call `POST /oauth2/token` to obtain an ACR access token that will allow us to use the `GET /v2/_catalog` API. Here's how such a call looks when done via `curl`:
|
||||
|
||||
```bash
|
||||
export registry="contosoregistry.azurecr.io"
|
||||
export acr_refresh_token="eyJ...L7a"
|
||||
export scope="registry:catalog:*"
|
||||
curl -v -X POST -H "Content-Type: application/x-www-form-urlencoded" -d \
|
||||
"grant_type=refresh_token&service=$registry&scope=$scope&refresh_token=$acr_refresh_token" \
|
||||
https://$registry/oauth2/token
|
||||
```
|
||||
|
||||
The body of the POST message is a querystring-like text that specifies the following values:
|
||||
- `grant_type` which is expected to be `refresh_token`.
|
||||
- `service`, which must indicate the name of your Azure container registry. You obtained this from the `Www-Authenticate` response header from the challenge.
|
||||
- `scope`, which is expected to be a valid [scope](https://docs.docker.com/registry/spec/auth/scope/), and can be specified more than once for multiple scope requests. You obtained this from the `Www-Authenticate` response header from the challenge.
|
||||
- `refresh_token`, which must be a valid ACR refresh token, as obtained by calling `POST /oauth2/exchange`.
|
||||
|
||||
The outcome of this operation will be a response with status 200 OK and a body with the following JSON payload:
|
||||
```json
|
||||
{"access_token":"eyJ...xcg"}
|
||||
```
|
||||
This response is the ACR access token which you can inspect with [jwt.io](https://jwt.io/). You can now use it to call APIs exposed by the Azure Container Registry
|
||||
|
||||
## Calling an Azure Container Registry API
|
||||
|
||||
In this example we'll call the `GET /v2/_catalog` API on an Azure Container Registry. Assume you have the following:
|
||||
1. A valid container registry, which here we'll call `contosoregistry.azurecr.io`.
|
||||
2. A valid ACR access token, created with the correct scope for the API we're going to call.
|
||||
|
||||
Here's how a call to the `GET /v2/_catalog` API of the given registry would look like when done via `curl`:
|
||||
|
||||
```bash
|
||||
export registry="contosoregistry.azurecr.io"
|
||||
export acr_access_token="eyJ...xcg"
|
||||
curl -v -H "Authorization: Bearer $acr_access_token" https://$registry/v2/_catalog
|
||||
```
|
||||
Note that `curl` by default does the request as a `GET` unless you specify a different verb with the `-X` modifier.
|
||||
|
||||
This should result in a status 200 OK, and a body with a JSON payload listing the repositories held in this registry:
|
||||
|
||||
```json
|
||||
{"repositories":["alpine","hello-world","contoso-marketing"]}
|
||||
```
|
||||
|
||||
### Full script to call Azure Container Registry API
|
||||
This is a summary script of the points discussed above. The first three variables have to be filled out.
|
||||
- Variable `registry` can be something like `"contosoregistry.azurecr.io"`.
|
||||
- The AAD access token and AAD refresh token values can be obtained from the Azure CLI, after running az login check file `$HOME/.azure/accessTokens.json` (`%HOMEDRIVE%%HOMEPATH%\.azure\accessTokens.json` in Windows) for the token values.
|
||||
|
||||
Note that stale AAD tokens will result in this script failing to obtain an ACR refresh token, and therefore it won't succeed in obtaining an ACR access token or in executing the operation against the registry.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
export registry=" --- you have to fill this out --- "
|
||||
export aad_refresh_token=" --- you have to fill this out --- "
|
||||
export aad_access_token=" --- you have to fill this out --- "
|
||||
|
||||
export operation="/v2/_catalog"
|
||||
|
||||
export acr_refresh_token=$(curl -s -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=access_token_refresh_token&service=$registry&refresh_token=$aad_refresh_token&access_token=$aad_access_token" https://$registry/oauth2/exchange | jq '.refresh_token' | sed -e 's/^"//' -e 's/"$//')
|
||||
echo "ACR Refresh Token"
|
||||
echo $acr_refresh_token
|
||||
|
||||
export acr_username="00000000-0000-0000-0000-000000000000"
|
||||
|
||||
export challenge=$(curl -vs https://$registry$operation 2>&1 | grep "Www-Authenticate:")
|
||||
echo "Challenge"
|
||||
echo $challenge
|
||||
|
||||
export scope=$(echo $challenge | egrep -o 'scope=\"([^\"]*)\"' | egrep -o '\"([^\"]*)\"' | sed -e 's/^"//' -e 's/"$//')
|
||||
echo "Scope"
|
||||
echo $scope
|
||||
|
||||
export acr_access_token=$(curl -s -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=refresh_token&service=$registry&scope=$scope&refresh_token=$acr_refresh_token" https://$registry/oauth2/token | jq '.access_token' | sed -e 's/^"//' -e 's/"$//')
|
||||
echo "ACR Access Token"
|
||||
echo $acr_access_token
|
||||
|
||||
export catalog=$(curl -s -H "Authorization: Bearer $acr_access_token" https://$registry$operation)
|
||||
echo "Catalog"
|
||||
echo $catalog
|
||||
```
|
66
docs/FAQ.md
66
docs/FAQ.md
|
@ -18,4 +18,68 @@ http://kubernetes.io/docs/user-guide/images/#using-azure-container-registry-acr
|
|||
|
||||
## How to access Docker Registry HTTP API V2?
|
||||
ACR supports Docker Registry HTTP API V2. The APIs can be accessed at
|
||||
https://<your registry login server>/v2/
|
||||
https://\<your registry login server\>/v2/
|
||||
|
||||
## Is Azure Premium Storage account supported?
|
||||
Azure Premium Storage account is not supported.
|
||||
|
||||
## How to get login credentials for a container registry?
|
||||
|
||||
Please make sure admin is enabled.
|
||||
|
||||
Using `az cli`
|
||||
```
|
||||
az acr credential show -n myRegistry
|
||||
```
|
||||
|
||||
Using `Azure Powershell`
|
||||
```
|
||||
Invoke-AzureRmResourceAction -Action listCredentials -ResourceType Microsoft.ContainerRegistry/registries -ResourceGroupName myResourceGroup -ResourceName myRegistry
|
||||
```
|
||||
|
||||
## How to get login credentials in an ARM deployment template?
|
||||
|
||||
Please make sure admin is enabled.
|
||||
|
||||
```
|
||||
{
|
||||
"password": "[listCredentials(resourceId('Microsoft.ContainerRegistry/registries', 'myRegistry'), '2017-03-01').passwords[0].value]"
|
||||
}
|
||||
```
|
||||
|
||||
To get the second password
|
||||
|
||||
```
|
||||
{
|
||||
"password": "[listCredentials(resourceId('Microsoft.ContainerRegistry/registries', 'myRegistry'), '2017-03-01').passwords[1].value]"
|
||||
}
|
||||
```
|
||||
|
||||
## How to update my registry to use the regenerated storage account access key?
|
||||
|
||||
Using `az cli` to update the storage account for your registry
|
||||
```
|
||||
az acr update -n myRegistry --storage-account-name myStorageAccount
|
||||
```
|
||||
|
||||
Your can find `myStorageAccount` to your registry by the following command
|
||||
```
|
||||
az acr show -n myRegistry --query storageAccount.name
|
||||
```
|
||||
|
||||
## How to log into my registry when running the CLI in a container?
|
||||
|
||||
You need to run the CLI container by mounting the Docker socket
|
||||
```
|
||||
docker run -it -v /var/run/docker.sock:/var/run/docker.sock azuresdk/azure-cli-python
|
||||
```
|
||||
|
||||
In the container, you can install `docker` by
|
||||
```
|
||||
apk add docker
|
||||
```
|
||||
|
||||
Then you can log into your registry by
|
||||
```
|
||||
az acr login -n MyRegistry
|
||||
```
|
||||
|
|
|
@ -35,3 +35,17 @@ az account set --subscription <correct-subscription>
|
|||
|
||||
See [this] (#RegisterSub) and [this] (#SetCorrectSub)
|
||||
|
||||
## Image exists in my ACR but, docker pull returns "image not found"
|
||||
|
||||
Please make sure you login before you pull/push repositories
|
||||
```
|
||||
docker login <yourregistry>.azurecr.io
|
||||
```
|
||||
|
||||
## Configuring a custom domain for azure container registry
|
||||
|
||||
Azure container registries have a typical login url of the format `*.azurecr.io`. A customer might like to use a custom domain for the registry. Follow [this guide](custom-domain/README.md) to achieve that.
|
||||
|
||||
## Moving repositories to a new registry
|
||||
|
||||
To move your repositories to a newly created registry, follow [this guide](move-repositories-to-new-registry/README.md).
|
|
@ -0,0 +1,56 @@
|
|||
# How to use a custom domain for azure container registry
|
||||
|
||||
Azure Container registries has a typical login url of the format `*.azurecr.io`. A customer might like to have a custom domain that associate with its own organization. The following is the guide on how to achieve that.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
For this example, we suppose that you want to associate `registry.contoso.com` with a Azure Container Registry. You would need the following:
|
||||
|
||||
* Setup your organization's DNS zone `.contoso.com`. To create one on Azure, you can follow [this guide](https://docs.microsoft.com/en-us/azure/dns/dns-getstarted-create-dnszone-portal)
|
||||
* SSL certificate for `registry.contoso.com`, we would call it `contoso.pfx`. Put the password of the certificate to a file named `pwd.txt`. You would optionally also need your signing CA certificate's URL, such as `http://www.contoso.com/pki/ca.cert`
|
||||
* An instance of Azure Container Registry service as the backend. In this example we would assume it's `docker-registry-contoso.azurecr.io`
|
||||
|
||||
## Steps
|
||||
|
||||
### Upload your cert into Azure Key Vault
|
||||
|
||||
Under [key-vault-setup/](key-vault-setup/), run the following:
|
||||
|
||||
1. (Optional) Create an Azure Key Vault, if you don't already have one:
|
||||
|
||||
`.\ensure-vault.ps1 -subscriptionName <subscription> -resourceGroupName <resourceGroup> -vaultName <new VaultName>`
|
||||
|
||||
2. Upload `contoso.pfx` to Azure Key Vault:
|
||||
|
||||
`.\upload-cert.ps1 -pfxFilePath <pfxFile> -pfxPwFile <pwdFile> -secretName <new SecretName> -vaultName <vaultName>`
|
||||
|
||||
### Deploy and configure an Nginx Docker image on a new Azure VM
|
||||
|
||||
Deploy via Azure Portal
|
||||
|
||||
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Facr%2Fmaster%2Fdocs%2Fcustom-domain%2Fdocker-vm-deploy%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://azuredeploy.net/deploybutton.png"/>
|
||||
</a>
|
||||
<a href="http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Facr%2Fmaster%2Fdocs%2Fcustom-domain%2Fdocker-vm-deploy%2Fazuredeploy.json" target="_blank">
|
||||
<img src="http://armviz.io/visualizebutton.png"/>
|
||||
</a>
|
||||
|
||||
Alternatively, to deploy using powershell script, [docker-vm-deploy/](docker-vm-deploy/), do the following:
|
||||
|
||||
1. Edit [azuredeploy.parameters.json](docker-vm-deploy/azuredeploy.parameters.json) and populate all necessary parameters
|
||||
|
||||
2. Run the following script to create the new VM:
|
||||
|
||||
`.\deploy.ps1 -resourceGroupName <resourceGroup>`
|
||||
|
||||
### Configure DNS zone
|
||||
|
||||
Configure the DNS zone so `registry.contoso.com` points to the Azure VM you have just created. If you are using an Azure DNS Zone. You can use the following command:
|
||||
|
||||
`New-AzureRmDnsRecordSet -Name <registry> -RecordType CNAME -ZoneName <contoso.com> -ResourceGroupName <resourceGroup> -Ttl <Ttl> -DnsRecords (New-AzureRmDnsRecordConfig -Cname <AddrToAboveVM>)`
|
||||
|
||||
## Quick verification
|
||||
|
||||
A simple way to test the setup is to call `docker login` to quickly confirm that the requests are properly forwarded:
|
||||
|
||||
`docker login -u <username> -p <password> registry.contoso.com`
|
|
@ -0,0 +1,270 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"newStorageAccountName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Unique DNS Name for the Storage Account where the Virtual Machine's disks will be placed."
|
||||
}
|
||||
},
|
||||
"adminUsername": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Username for the Virtual Machine."
|
||||
}
|
||||
},
|
||||
"adminPassword": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "Password for the Virtual Machine."
|
||||
}
|
||||
},
|
||||
"dnsNameForVM": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
|
||||
}
|
||||
},
|
||||
"ubuntuOSVersion": {
|
||||
"type": "string",
|
||||
"defaultValue": "14.04.4-LTS",
|
||||
"metadata": {
|
||||
"description": "The Ubuntu version for deploying the Docker containers. This will pick a fully patched image of this given Ubuntu version. Allowed values: 14.04.4-LTS, 15.10, 16.04.0-LTS"
|
||||
},
|
||||
"allowedValues": [
|
||||
"14.04.4-LTS",
|
||||
"15.10",
|
||||
"16.04.0-LTS"
|
||||
]
|
||||
},
|
||||
"newVmName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Name of the new VM to create"
|
||||
}
|
||||
},
|
||||
"vaultName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Name of Key Vault that has a secret"
|
||||
}
|
||||
},
|
||||
"vaultResourceGroup": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Resource Group of Key Vault that has a secret"
|
||||
}
|
||||
},
|
||||
"secretUrlWithVersion": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Url of the certificate in Key Vault"
|
||||
}
|
||||
},
|
||||
"certThumbPrint": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Thumb print for the key for above url"
|
||||
}
|
||||
},
|
||||
"dnsFrontEnd": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "DNS for the front end service."
|
||||
}
|
||||
},
|
||||
"backendRegistry": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Azure container registry serving as backend."
|
||||
}
|
||||
},
|
||||
"caCertUrl": {
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"metadata": {
|
||||
"description": "URL for the signing certificate authority cert. If any"
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"imagePublisher": "Canonical",
|
||||
"imageOffer": "UbuntuServer",
|
||||
"OSDiskName": "osdiskfordockersimple",
|
||||
"nicName": "[concat(parameters('newVmName'), 'NIC')]",
|
||||
"addressPrefix": "10.0.0.0/16",
|
||||
"subnetName": "Subnet",
|
||||
"subnetPrefix": "10.0.0.0/24",
|
||||
"storageAccountType": "Standard_LRS",
|
||||
"publicIPAddressName": "[concat(parameters('newVmName'), 'PublicIPD')]",
|
||||
"publicIPAddressType": "Dynamic",
|
||||
"vmStorageAccountContainerName": "vhds",
|
||||
"vmSize": "Standard_F1",
|
||||
"virtualNetworkName": "[concat(parameters('newVmName'), 'VNET')]",
|
||||
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]",
|
||||
"subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Storage/storageAccounts",
|
||||
"name": "[parameters('newStorageAccountName')]",
|
||||
"apiVersion": "2015-05-01-preview",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"accountType": "[variables('storageAccountType')]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-05-01-preview",
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "[variables('publicIPAddressType')]",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[parameters('dnsNameForVM')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-05-01-preview",
|
||||
"type": "Microsoft.Network/virtualNetworks",
|
||||
"name": "[variables('virtualNetworkName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"addressSpace": {
|
||||
"addressPrefixes": [
|
||||
"[variables('addressPrefix')]"
|
||||
]
|
||||
},
|
||||
"subnets": [
|
||||
{
|
||||
"name": "[variables('subnetName')]",
|
||||
"properties": {
|
||||
"addressPrefix": "[variables('subnetPrefix')]"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-05-01-preview",
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"name": "[variables('nicName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
|
||||
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig1",
|
||||
"properties": {
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
|
||||
},
|
||||
"subnet": {
|
||||
"id": "[variables('subnetRef')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2015-05-01-preview",
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"name": "[parameters('newVmName')]",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]",
|
||||
"[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "[variables('vmSize')]"
|
||||
},
|
||||
"osProfile": {
|
||||
"computerName": "[parameters('newVmName')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"adminPassword": "[parameters('adminPassword')]",
|
||||
"secrets": [
|
||||
{
|
||||
"sourceVault": {
|
||||
"id": "[resourceId(parameters('vaultResourceGroup'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]"
|
||||
},
|
||||
"vaultCertificates": [
|
||||
{
|
||||
"certificateUrl": "[parameters('secretUrlWithVersion')]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"storageProfile": {
|
||||
"imageReference": {
|
||||
"publisher": "[variables('imagePublisher')]",
|
||||
"offer": "[variables('imageOffer')]",
|
||||
"sku": "[parameters('ubuntuOSVersion')]",
|
||||
"version": "latest"
|
||||
},
|
||||
"osDisk": {
|
||||
"name": "osdisk1",
|
||||
"vhd": {
|
||||
"uri": "[concat('http://',parameters('newStorageAccountName'),'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]"
|
||||
},
|
||||
"caching": "ReadWrite",
|
||||
"createOption": "FromImage"
|
||||
}
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"name": "[concat(parameters('newVmName'),'/docker')]",
|
||||
"apiVersion": "2015-05-01-preview",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Compute/virtualMachines/', parameters('newVmName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Azure.Extensions",
|
||||
"type": "DockerExtension",
|
||||
"typeHandlerVersion": "1.0",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": { }
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"name": "[concat(parameters('newVmName'),'/initdevbox')]",
|
||||
"apiVersion": "2015-06-15",
|
||||
"location": "[resourceGroup().location]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Compute/virtualMachines/', parameters('newVmName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"publisher": "Microsoft.Azure.Extensions",
|
||||
"type": "CustomScript",
|
||||
"typeHandlerVersion": "2.0",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"settings": {
|
||||
"fileUris": ["https://raw.githubusercontent.com/Azure/acr/master/docs/custom-domain/docker-vm-deploy/deploy-nginx-docker.sh"]
|
||||
},
|
||||
"protectedSettings": {
|
||||
"commandToExecute": "[concat('./deploy-nginx-docker.sh ', parameters('certThumbPrint'), ' ', parameters('backendRegistry'), ' ', parameters('dnsFrontEnd'), ' \"', parameters('caCertUrl'), '\"')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"newVmName": {
|
||||
"value": "<My VM>"
|
||||
},
|
||||
"newStorageAccountName": {
|
||||
"value": "<My new Storage>"
|
||||
},
|
||||
"adminUsername": {
|
||||
"value": "<Admin User>"
|
||||
},
|
||||
"adminPassword": {
|
||||
"value": "<Password>"
|
||||
},
|
||||
"dnsNameForVM": {
|
||||
"value": "<VM DNS>"
|
||||
},
|
||||
"vaultName": {
|
||||
"value": "<My Valut>"
|
||||
},
|
||||
"vaultResourceGroup": {
|
||||
"value": "<Resource Group>"
|
||||
},
|
||||
"secretUrlWithVersion": {
|
||||
"value": "<Secret URL>"
|
||||
},
|
||||
"certThumbPrint": {
|
||||
"value": "<Key Thumbprint>"
|
||||
},
|
||||
"dnsFrontEnd": {
|
||||
"value": "<Front End URL>"
|
||||
},
|
||||
"backendRegistry": {
|
||||
"value": "<Azure Registry URL>"
|
||||
},
|
||||
"caCertUrl": {
|
||||
"value": "<Optional: CA Cert URL>"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
CERT_FINGERPRINT=$1
|
||||
export BACKEND_HOST=$2
|
||||
export FRONTEND_HOST=$3
|
||||
CA_CERT_URL=$4
|
||||
|
||||
SOURCE_ROOT="https://raw.githubusercontent.com/Azure/acr/master"
|
||||
|
||||
curl "$SOURCE_ROOT/docs/custom-domain/docker-vm-deploy/setup-certs.sh" -o setup-certs.sh
|
||||
chmod +x ./setup-certs.sh
|
||||
. ./setup-certs.sh $CERT_FINGERPRINT $CA_CERT_URL
|
||||
|
||||
export CONTAINER_CERT_LOCATION="/etc/nginx/ssl/cert.crt"
|
||||
export CONTAINER_PRV_LOCATION="/etc/nginx/ssl/private.key"
|
||||
|
||||
curl "$SOURCE_ROOT/docs/custom-domain/docker-vm-deploy/docker-compose.yml.template" -o docker-compose.yml.template
|
||||
sudo -E envsubst '$CERT_LOCATION$PRV_LOCATION$CONTAINER_CERT_LOCATION$CONTAINER_PRV_LOCATION' < docker-compose.yml.template > docker-compose.yml
|
||||
|
||||
export CERT_LOCATION=$CONTAINER_CERT_LOCATION
|
||||
export PRV_LOCATION=$CONTAINER_PRV_LOCATION
|
||||
|
||||
curl "$SOURCE_ROOT/docs/custom-domain/docker-vm-deploy/nginx.conf.template" -o nginx.conf.template
|
||||
sudo -E envsubst '$FRONTEND_HOST$BACKEND_HOST$CERT_LOCATION$PRV_LOCATION' < nginx.conf.template > nginx.conf
|
||||
|
||||
## Docker installation extension installs docker in the background
|
||||
## So we cannot make assumption about its completion time
|
||||
until docker-compose up
|
||||
do
|
||||
sleep 10
|
||||
done
|
|
@ -0,0 +1,11 @@
|
|||
param (
|
||||
$templateFile = 'azuredeploy.json',
|
||||
$templateParams = 'azuredeploy.parameters.json',
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$resourceGroupName
|
||||
)
|
||||
|
||||
New-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile $templateFile -TemplateParameterFile $templateParams
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
proxy:
|
||||
image: nginx
|
||||
|
||||
ports:
|
||||
- 443:443
|
||||
|
||||
volumes:
|
||||
- ${CERT_LOCATION}:${CONTAINER_CERT_LOCATION}:ro
|
||||
- ${PRV_LOCATION}:${CONTAINER_PRV_LOCATION}:ro
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
|
@ -0,0 +1,46 @@
|
|||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log; # main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
|
||||
upstream backends {
|
||||
server ${BACKEND_HOST}:443;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl; # 'ssl' parameter tells NGINX to decrypt the traffic
|
||||
server_name ${FRONTEND_HOST};
|
||||
ssl_certificate ${CERT_LOCATION}; # The certificate file
|
||||
ssl_certificate_key ${PRV_LOCATION}; # The private key file
|
||||
|
||||
location / {
|
||||
proxy_set_header Host ${BACKEND_HOST};
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_pass https://backends;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#!/bin/bash
|
||||
|
||||
CERT_FINGERPRINT=$1
|
||||
CA_CERT_URL=$2
|
||||
|
||||
CERT_FINGERPRINT=`echo $CERT_FINGERPRINT | tr [a-z] [A-Z]`
|
||||
|
||||
if [ ! -z "$CA_CERT_URL" ]; then
|
||||
|
||||
curl $CA_CERT_URL -o ca_cert.crt
|
||||
|
||||
set +e
|
||||
certDetails=`openssl x509 -in ca_cert.crt -text -noout`
|
||||
set -e
|
||||
|
||||
# if it is not PEM, it must be DER
|
||||
if [ -z "$certDetails" ]; then
|
||||
openssl x509 -in ca_cert.crt -inform der -outform pem -out ca_cert_pem.crt
|
||||
else
|
||||
mv ca_cert.crt ca_cert_pem.crt
|
||||
fi
|
||||
|
||||
sudo cat "/var/lib/waagent/$CERT_FINGERPRINT.crt" ca_cert_pem.crt > cert.crt
|
||||
export CERT_LOCATION=`pwd`/cert.crt
|
||||
|
||||
else
|
||||
export CERT_LOCATION=/var/lib/waagent/${CERT_FINGERPRINT}.crt
|
||||
fi
|
||||
|
||||
export PRV_LOCATION=/var/lib/waagent/${CERT_FINGERPRINT}.prv
|
|
@ -0,0 +1,16 @@
|
|||
param (
|
||||
$subscriptionName,
|
||||
$resourceGroupName,
|
||||
$vaultName
|
||||
}
|
||||
|
||||
if ($subscriptionName)
|
||||
{
|
||||
Select-AzureRmSubscription -SubscriptionName $subscriptionName
|
||||
}
|
||||
|
||||
Get-AzureRmKeyVault -vaultName $vaultName -ev notPresent -ea 0
|
||||
if ($notPresent)
|
||||
{
|
||||
New-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $resourceGroupName -sku standard -EnabledForDeployment
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$pfxFilePath,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$pfxPwFile,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$secretName,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$vaultName
|
||||
)
|
||||
|
||||
$pfxPw = [IO.File]::ReadAllText($pfxPwFile)
|
||||
$pfxContent = get-content $pfxFilePath -Encoding Byte
|
||||
$pfxContentEncoded = [System.Convert]::ToBase64String($pfxContent)
|
||||
|
||||
$certBundleObj = @"
|
||||
{
|
||||
"data": "$pfxContentEncoded",
|
||||
"dataType" :"pfx",
|
||||
"password": "$pfxPw"
|
||||
}
|
||||
"@
|
||||
|
||||
$bundleObjBytes = [System.Text.Encoding]::UTF8.GetBytes($certBundleObj)
|
||||
$bundleObjEncoded = [System.Convert]::ToBase64String($bundleObjBytes)
|
||||
$secretValue = ConvertTo-SecureString -String $bundleObjEncoded -AsPlainText -Force
|
||||
|
||||
Set-AzureKeyVaultSecret -Name $secretName -SecretValue $secretValue -VaultName $vaultName
|
|
@ -0,0 +1,35 @@
|
|||
# Using Azure Containter Registry With CircleCI
|
||||
|
||||
For configuration of your Docker build using CircleCI, refer [https://circleci.com/docs/1.0/docker/](https://circleci.com/docs/1.0/docker/)
|
||||
|
||||
Here is a sample `circle.yml ` file that can be used with Azure Container Registry using three environment variables as a part of the build, that builds and pushes an image to the registry.
|
||||
|
||||
|
||||
``` yml
|
||||
machine:
|
||||
services:
|
||||
- docker
|
||||
|
||||
dependencies:
|
||||
override:
|
||||
- docker info
|
||||
- docker build --rm=false -t $REGISTRY_HOST/circleci .
|
||||
|
||||
test:
|
||||
override:
|
||||
- docker run -d hello-world
|
||||
|
||||
deployment:
|
||||
hub:
|
||||
branch: master
|
||||
commands:
|
||||
- docker login -e $DOCKER_USER -u $DOCKER_USER -p $DOCKER_PASSWORD $REGISTRY_HOST
|
||||
- docker push $REGISTRY_HOST/circleci
|
||||
```
|
||||
|
||||
| Enviroment Variable | Description |
|
||||
| --------------------|-------------|
|
||||
| REGISTRY_HOST | Login server host for your Registry |
|
||||
| DOCKER_USER | Service principal or admin user for the registry |
|
||||
| DOCKER_PASSWORD | User's password that would be used for docker login |
|
||||
|
До Ширина: | Высота: | Размер: 35 KiB После Ширина: | Высота: | Размер: 35 KiB |
До Ширина: | Высота: | Размер: 20 KiB После Ширина: | Высота: | Размер: 20 KiB |
До Ширина: | Высота: | Размер: 36 KiB После Ширина: | Высота: | Размер: 36 KiB |
Загрузка…
Ссылка в новой задаче