Abilitare HTTPS automatico con Caddy in un contenitore sidecar
Questo articolo descrive come Caddy può essere usato come contenitore sidecar in un gruppo di contenitori e funge da proxy inverso per fornire un endpoint HTTPS gestito automaticamente per l'applicazione.
Caddy è un server Web open source potente e pronto per le aziende, con HTTPS automatico, scritto in Go e rappresenta un'alternativa a Nginx.
L'automazione dei certificati è possibile in quanto Caddy supporta l'API ACMEv2 (RFC 8555) che interagisce con Let's Encrypt per rilasciare i certificati.
In questo esempio, solo il contenitore Caddy viene esposto sulle porte 80/TCP e 443/TCP. L'applicazione dietro il proxy inverso rimane privata. La comunicazione di rete tra Caddy e l'applicazione avviene tramite localhost.
Nota
Questo è in contrasto con la comunicazione all'interno del gruppo di contenitori conosciuta da Docker Compose, dove è possibile fare riferimento ai contenitori in base al nome.
L'esempio monta il Caddyfile necessario per configurare il proxy inverso da una condivisione file ospitata in un account di Archiviazione di Azure.
Nota
Per le distribuzioni di produzione, la maggior parte degli utenti vuole creare il bake del Caddyfile in un'immagine Docker personalizzata basata su Caddy. In questo modo, non è necessario montare i file nel contenitore.
Prerequisiti
Usare l'ambiente Bash in Azure Cloud Shell. Per altre informazioni, vedere Avvio rapido su Bash in Azure Cloud Shell.
Se si preferisce eseguire i comandi di riferimento dell'interfaccia della riga di comando in locale, installare l'interfaccia della riga di comando di Azure. Per l'esecuzione in Windows o macOS, è consigliabile eseguire l'interfaccia della riga di comando di Azure in un contenitore Docker. Per altre informazioni, vedere Come eseguire l'interfaccia della riga di comando di Azure in un contenitore Docker.
Se si usa un'installazione locale, accedere all'interfaccia della riga di comando di Azure con il comando az login. Per completare il processo di autenticazione, seguire la procedura visualizzata nel terminale. Per altre opzioni di accesso, vedere Accedere tramite l'interfaccia della riga di comando di Azure.
Quando richiesto, al primo utilizzo installare l'estensione dell'interfaccia della riga di comando di Azure. Per altre informazioni sulle estensioni, vedere Usare le estensioni con l'interfaccia della riga di comando di Azure.
Eseguire az version per trovare la versione e le librerie dipendenti installate. Per eseguire l'aggiornamento alla versione più recente, eseguire az upgrade.
- Questo articolo richiede la versione 2.0.55 o successiva dell'interfaccia della riga di comando di Azure. Se si usa Azure Cloud Shell, la versione più recente è già installata.
Preparare Caddyfile
Creare un file denominato Caddyfile
e incollare la configurazione seguente. Questa configurazione crea una configurazione del proxy inverso, che punta al contenitore dell'applicazione in ascolto su 5000/TCP.
my-app.westeurope.azurecontainer.io {
reverse_proxy http://localhost:5000
}
È importante notare che la configurazione fa riferimento a un nome di dominio anziché a un indirizzo IP. Caddy deve essere raggiungibile da questo URL per eseguire il passaggio di verifica richiesto dal protocollo ACME e recuperare correttamente un certificato da Let's Encrypt.
Nota
Per la distribuzione di produzione, gli utenti potrebbero voler usare un nome di dominio che controllano, ad esempio api.company.com
e creare un record CNAME che punta verso my-app.westeurope.azurecontainer.io
, ad esempio. In tal caso, è necessario assicurarsi che il nome di dominio personalizzato venga usato anche nel Caddyfile, anziché quello assegnato da Azure (ad esempio, *.westeurope.azurecontainer.io
). È inoltre necessario fare riferimento al nome di dominio personalizzato nella configurazione YAML di ACI descritta più avanti in questo esempio.
Preparare un account di archiviazione
Creare un account di archiviazione
az storage account create \
--name <storage-account> \
--resource-group <resource-group> \
--location westeurope
Archiviare la stringa di connessione a una variabile di ambiente
AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string --name <storage-account> --resource-group <resource-group> --output tsv)
Creare le condivisioni file necessarie per archiviare lo stato del contenitore e la configurazione Caddy.
az storage share create \
--name proxy-caddyfile \
--account-name <storage-account>
az storage share create \
--name proxy-config \
--account-name <storage-account>
az storage share create \
--name proxy-data \
--account-name <storage-account>
Recuperare le chiavi dell'account di archiviazione e annotarle per un uso successivo
az storage account keys list -g <resource-group> -n <storage-account>
Distribuire il gruppo di contenitori
Creare un file YAML
Creare un file denominato ci-my-app.yaml
e incollare il contenuto seguente. Assicurarsi di sostituire <account-key>
con una delle chiavi di accesso ricevute in precedenza e <storage-account>
di conseguenza.
Questo file YAML definisce due contenitori reverse-proxy
e my-app
. Il contenitore reverse-proxy
monta le tre condivisioni file create in precedenza. La configurazione espone anche la porta 80/TCP e 443/TCP del contenitore reverse-proxy
. La comunicazione tra entrambi i contenitori avviene solo in localhost.
Nota
È importante notare che la chiave dnsNameLabel
definisce il nome DNS pubblico, in cui il gruppo di istanze del contenitore sarà raggiungibile, deve corrispondere al nome di dominio completo definito nel Caddyfile
name: ci-my-app
apiVersion: "2021-10-01"
location: westeurope
properties:
containers:
- name: reverse-proxy
properties:
image: caddy:2.6
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
resources:
requests:
memoryInGB: 1.0
cpu: 1.0
limits:
memoryInGB: 1.0
cpu: 1.0
volumeMounts:
- name: proxy-caddyfile
mountPath: /etc/caddy
- name: proxy-data
mountPath: /data
- name: proxy-config
mountPath: /config
- name: my-app
properties:
image: mcr.microsoft.com/azuredocs/aci-helloworld
ports:
- port: 5000
protocol: TCP
environmentVariables:
- name: PORT
value: 5000
resources:
requests:
memoryInGB: 1.0
cpu: 1.0
limits:
memoryInGB: 1.0
cpu: 1.0
ipAddress:
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
type: Public
dnsNameLabel: my-app
osType: Linux
volumes:
- name: proxy-caddyfile
azureFile:
shareName: proxy-caddyfile
storageAccountName: "<storage-account>"
storageAccountKey: "<account-key>"
- name: proxy-data
azureFile:
shareName: proxy-data
storageAccountName: "<storage-account>"
storageAccountKey: "<account-key>"
- name: proxy-config
azureFile:
shareName: proxy-config
storageAccountName: "<storage-account>"
storageAccountKey: "<account-key>"
Distribuire il gruppo di contenitori
Creare un gruppo di risorse con il comando az group create:
az group create --name <resource-group> --location westeurope
Distribuire il gruppo di contenitori con il comando az container create, passando il file YAML come argomento.
az container create --resource-group <resource-group> --file ci-my-app.yaml
Visualizzare lo stato della distribuzione
Per visualizzare lo stato della distribuzione, usare il comando az container show seguente:
az container show --resource-group <resource-group> --name ci-my-app --output table
Verificare la connessione TLS
Prima di verificare se tutto è andato bene, lasciare che il gruppo di contenitori si avvii completamente e che Caddy richieda un certificato.
OpenSSL
A tale scopo, è possibile usare il sottocomando s_client
di OpenSSL.
echo "Q" | openssl s_client -connect my-app.westeurope.azurecontainer.io:443
CONNECTED(00000188)
---
Certificate chain
0 s:CN = my-app.westeurope.azurecontainer.io
i:C = US, O = Let's Encrypt, CN = R3
1 s:C = US, O = Let's Encrypt, CN = R3
i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
i:O = Digital Signature Trust Co., CN = DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEgTCCA2mgAwIBAgISAxxidSnpH4vVuCZk9UNG/pd2MA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMzA0MDYxODAzMzNaFw0yMzA3MDUxODAzMzJaMC4xLDAqBgNVBAMT
I215LWFwcC53ZXN0ZXVyb3BlLmF6dXJlY29udGFpbmVyLmlvMFkwEwYHKoZIzj0C
AQYIKoZIzj0DAQcDQgAEaaN/wGyFcimM+1O4WzbFgO6vIlXxXqp9vgmLZHpFrNwV
aO8JbaB7hE+M5EAg34LDY80RyHgY+Ff4vTh2Z96rVqOCAl4wggJaMA4GA1UdDwEB
/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/
BAIwADAdBgNVHQ4EFgQUoL5DP+4PWiyE79hL5o+v8uymHdAwHwYDVR0jBBgwFoAU
FC6zF7dYVsuuUAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzAB
hhVodHRwOi8vcjMuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5p
LmxlbmNyLm9yZy8wLgYDVR0RBCcwJYIjbXktYXBwLndlc3RldXJvcGUuYXp1cmVj
b250YWluZXIuaW8wTAYDVR0gBEUwQzAIBgZngQwBAgEwNwYLKwYBBAGC3xMBAQEw
KDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwggEEBgor
BgEEAdZ5AgQCBIH1BIHyAPAAdgC3Pvsk35xNunXyOcW6WPRsXfxCz3qfNcSeHQmB
Je20mQAAAYdX8+CQAAAEAwBHMEUCIQC9Ztqd3DXoJhOIHBW+P7ketGrKlVA6nPZl
9CiOrn6t8gIgXHcrbBqItemndRMv+UJ3DaBfTkYOqECecOJCgLhSYNUAdgDoPtDa
PvUGNTLnVyi8iWvJA9PL0RFr7Otp4Xd9bQa9bgAAAYdX8+CAAAAEAwBHMEUCIBJ1
24z44vKFUOLCi1a7ymVuWErkmLb/GtysvcxILaj0AiEAr49hyKfen4BbSTwC8Fg4
/LgZnn2F3uHI+9p+ZMO9xTAwDQYJKoZIhvcNAQELBQADggEBACqxa21eiW3JrZwk
FHgpd6SxhUeecrYXxFNva1Y6G//q2qCmGeKK3GK+ZGPqDtcoASH5t5ghV4dIT4WU
auVDLFVywXzR8PT6QUu3W8QxU+W7406twBf23qMIgrF8PIWhStI5mn1uCpeqlnf5
HpRaj2f5/5n19pcCZcrRx94G9qhPYdMzuy4mZRhxXRqrpIsabqX3DC2ld8dszCvD
pkV61iuARgm3MIQz1yL/x5Bn4nywjnhYZA4KFktC0Ti55cPRh1mkzGQAsYQDdWrq
dVav+U9dOLQ4Sq4suaDmzDzApr+hpQSJhwgRN16+tLMyZ6INAU2JWKDxiyDTdOuH
jz456og=
-----END CERTIFICATE-----
subject=CN = my-app.westeurope.azurecontainer.io
issuer=C = US, O = Let's Encrypt, CN = R3
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 4208 bytes and written 401 bytes
Verification error: unable to get local issuer certificate
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 256 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 20 (unable to get local issuer certificate)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_128_GCM_SHA256
Session-ID: 85F1A4290F99A0DD28C8CB21EF4269E7016CC5D23485080999A8548057729B24
Session-ID-ctx:
Resumption PSK: 752D438C19A5DBDBF10781F863D5E5D9A8859230968A9EAFFF7BBA86937D004F
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 604800 (seconds)
TLS session ticket:
0000 - 2f 25 98 90 9d 46 9b 01-03 78 db bd 4d 64 b3 a6 /%...F...x..Md..
0010 - 52 c0 7a 8a b6 3d b8 4b-c0 d7 fc 04 e8 63 d4 bb R.z..=.K.....c..
0020 - 15 b3 25 b7 be 64 3d 30-2b d7 dc 7a 1a d1 22 63 ..%..d=0+..z.."c
0030 - 42 30 90 65 6b b5 e1 83-a3 6c 76 c8 f6 ae e9 31 B0.ek....lv....1
0040 - 45 91 33 57 8e 9f 4b 6a-2e 2c 9b f9 87 5f 71 1d E.3W..Kj.,..._q.
0050 - 5a 84 59 50 17 31 1f 62-2b 0e 1e e5 70 03 d9 e9 Z.YP.1.b+...p...
0060 - 50 1c 5d 1f a4 3c 8a 0e-f4 c5 7d ce 9e 5c 98 de P.]..<....}..\..
0070 - e5 .
Start Time: 1680808973
Timeout : 7200 (sec)
Verify return code: 20 (unable to get local issuer certificate)
Extended master secret: no
Max Early Data: 0
---
read R BLOCK
Browser Chrome
Passare a https://my-app.westeurope.azurecontainer.io
e verificare il certificato facendo clic sul lucchetto accanto all'URL.
Per visualizzare i dettagli del certificato, selezionare "Connessione sicura" seguita da "certificato valido".