我的 Azure 容器应用程序 (ACA) 和 Azure 存储帐户表之间的网络连接遇到困难。
我有一个使用 Docker 进行容器化的 python (Flask) 应用程序 API。我正在利用 Azure 容器注册表 (ACR) 和 ACA 以及 CICD 设置来提交到 GitHub 中的主分支。我最近想实现身份验证,因此我创建了一个Azure存储帐户表来验证API密钥。这在本地效果很好。它在云端根本不起作用。我已将其范围缩小到网络错误,我将对此进行详细说明。下面我将我在本地和云端所做的事情提供出来,希望你能帮助我解决问题。
构建 Docker 镜像
docker build -t testapp_${env}:${VERSION} --platform linux/amd64 .
使用表连接字符串运行 Docker 映像
docker run -p 8000:80 -e AZURE_TABLE_CONN_STRING='hardcodingfortesting' testapp_${env}:${VERSION}
发布成功
curl -X POST http://localhost:8000/parse-report \
-H "X-API-KEY: 123" \
-H "Content-Type: application/json" \
这个逻辑非常有效,我可以更改 API 密钥,它会告诉我它不匹配。
现在完全相同的包被推送到 ACR 和 ACA,当我尝试发布时出现错误。
发布不成功
curl -X POST https://removingforsecurity.io \
-H "X-API-KEY: 123" \
-H "Content-Type: application/json" \
我非常确定这是一个网络问题。这是因为在我的存储帐户的网络选项卡中,如果我将 公共网络访问 更改为 从所有网络启用,我可以成功 POST。
尝试 POST 后登录 ACA 时出错:
Content: {"odata.error":{"code":"AuthorizationFailure","message":{"lang":"en-US","value":"该请求无权执行此操作。 请求 ID:9e37b393-b002-006b-1217-64ed0a000000 时间:2024-02-20T16:08:39.0510443Z"}}}
我已尝试以下方法来解决此问题:
请让我知道我应该做什么。
编辑:添加 Dockerfile
# Python runtime image base
FROM python:3.10-slim
# Set the working directory in the container
WORKDIR /app
# Ensure requirements are copied
COPY requirements.txt /app/
# Install requirements
RUN pip install --no-cache-dir -r requirements.txt
# Copy application
COPY . /app
# Where to find application instance
ENV FLASK_APP=main_parser.py
# Expose port
EXPOSE 80
# Run command
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:80", "main_parser:app"]
Azure 容器应用程序 (ACA) 和 Azure 存储帐户表之间的授权问题可能是由于 IP 地址限制或托管标识权限读取访问角色造成的。
在 Azure 容器中使用存储挂载的指南 Apps
在 Azure 容器应用程序 (ACA) 中使用存储的指南,涵盖各种 存储
我按照 DOC 将 Flask Web 应用程序部署为 Azure 容器应用程序中的容器。
通过专用端点连接到 Azure 文件共享。
使用 Azure 容器 Registry 的专用链接设置专用端点。如果您使用专用链接,请确保在同一专用终结点上运行 Azure 存储和 Azure 容器。
以下带有 Azure 存储表显示的 Flask 代码,已部署到 Azure 容器应用程序:
应用程序.py:
import os
from flask import (Flask, redirect, render_template, request, send_from_directory, url_for)
from azure.data.tables import TableServiceClient
from azure.core.credentials import AzureNamedKeyCredential
app = Flask(__name__)
# Azure Storage Account details
account_name = "Azureaccount_name"
account_key = "Azureaccount_key"
table_name = "Azuretable_name"
table_service_endpoint = f"https://{account_name}.table.core.windows.net/"
# Create the AzureNamedKeyCredential
credential = AzureNamedKeyCredential(account_name, account_key)
# Create the TableServiceClient using the connection string
table_service_client = TableServiceClient(endpoint=table_service_endpoint, credential=credential)
# Get the table client for the specified table
table_client = table_service_client.get_table_client(table_name)
@app.route('/')
def index():
print('Request for index page received')
return render_template('index.html')
@app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path, 'static'),
'favicon.ico', mimetype='image/vnd.microsoft.icon')
@app.route('/hello', methods=['POST'])
def hello():
name = request.form.get('name')
if name:
print('Request for hello page received with name=%s' % name)
try:
entities = table_client.list_entities()
entities_list = []
for entity in entities:
entities_list.append(entity)
return render_template('hello.html', name=name, entities=entities_list)
except Exception as e:
error_message = f"An error occurred: {e}"
print(error_message)
return render_template('hello.html', name=name, error=error_message)
else:
print('Request for hello page received with no name or blank name -- redirecting')
return redirect(url_for('index'))
if __name__ == '__main__':
app.run()
hello.html:
<!doctype html>
<html>
<head>
<title>Hello Azure - Python Quickstart</title>
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
</head>
<body>
<main>
<div class="px-4 py-3 my-2 text-center">
<img class="d-block mx-auto mb-4" src="{{ url_for('static', filename='images/azure-icon.svg') }}" alt="Azure Logo" width="192" height="192"/>
<h1 class="display-6 fw-bold">Hello {{name}}</h1>
<p class="fs-5">It is nice to meet you!</p>
<a href="{{ url_for('index') }}" class="btn btn-primary btn-lg px-4 gap-3">Back home</a>
</div>
{% if entities %}
<div class="container">
<h2>Entities in the Azure Table:</h2>
<ul>
{% for entity in entities %}
<li>
<strong>PartitionKey:</strong> {{ entity.PartitionKey }} <br>
<strong>RowKey:</strong> {{ entity.RowKey }} <br>
{% for key, value in entity.items() if key not in ['PartitionKey', 'RowKey'] %}
<strong>{{ key }}:</strong> {{ value }} <br>
{% endfor %}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% if error %}
<div class="container">
<p>An error occurred: {{ error }}</p>
</div>
{% endif %}
</main>
</body>
</html>
index.html:
<!doctype html>
<html>
<head>
<title>Hello Azure - Python Quickstart</title>
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
</head>
<body>
<main>
<div class="px-4 py-3 my-2 text-center">
<img class="d-block mx-auto mb-4" src="{{ url_for('static', filename='images/azure-icon.svg') }}" alt="Azure Logo" width="192" height="192"/>
<h1 class="display-6 fw-bold text-primary">Welcome to Azure</h1>
</div>
<form method="post" action="{{url_for('hello')}}" class="col-md-6 mx-auto text-center">
<label for="name" class="form-label fw-bold fs-5">Could you please tell me your name?</label>
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center align-items-center my-1">
<input type="text" class="form-control" id="name" name="name" style="max-width: 256px;">
</div>
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center my-2">
<button type="submit" class="btn btn-primary btn-lg px-4 gap-3">Say Hello</button>
</div>
</form>
</main>
</body>
</html>
需求.txt:
Flask==2.2.2
gunicorn
Werkzeug==2.2.2
azure-storage-blob
azure-data-tables
Dockerfile:
# syntax=docker/dockerfile:1
FROM python:3.11
WORKDIR /code
COPY requirements.txt .
RUN pip3 install -r requirements.txt
COPY . .
EXPOSE 50505
ENTRYPOINT ["gunicorn", "app:app"]
.dockerignore
.git*
**/*.pyc
.venv/
本地:
从 Dockerfile 构建 Docker 映像。
docker build --tag flask-demo1 .
docker tag 8xxxxxe63 sampath344.azurecr.io/samapth-app/flask-demo:v2
az acr login
命令登录 Azure 容器注册表 (ACR),并将 Docker 映像推送到 Azure 容器注册表 (ACR)。az acr login --name "ContainerregistryName" --password "password" --username "password"
docker push sampath344.azurecr.io/samapth-app/flask-demo:v2
蔚蓝: