rob*_*bin 4 django django-storage docker docker-compose
我的问题归结为:我在 docker compose:app和中有两个服务storage。我正在寻找一种使用相同地址从应用程序内部和外部访问storage服务(端口 9000)的方法。
app是一个使用 django-storages 和 S3 后端的 Django 应用程序。
storage是一个minio服务器(S3兼容,仅用于开发)。
从app,我可以storage使用http://storage:9000进行访问。从外部 docker,我可以访问storagehttp ://localhost:9000或http://0.0.0.0:9000,甚至可以访问http://192.168.xxx.yyy(使用网络上的不同设备)。那里没有什么惊喜。
但是,当生成 URL 时,我不知道它是要在内部使用还是在外部使用(或两者兼而有之)。
docker-compose.yml
services:
app:
build: backend/
ports:
- "8000:8000"
volumes:
- ./backend/src:/app/src
command: /usr/local/bin/python src/manage.py runserver 0.0.0.0:8000
storage:
image: minio/minio:RELEASE.2019-06-19T18-24-42Z
volumes:
- storage:/data
environment:
MINIO_ACCESS_KEY: "DevelopmentAccessKey"
MINIO_SECRET_KEY: "DevelopmentSecretKey"
ports:
- "9000:9000"
command: minio server /data
volumes:
storage:
Run Code Online (Sandbox Code Playgroud)
我已经研究过更改后端以根据上下文生成端点 url,但这远非微不足道(并且仅用于开发,生产使用外部 S3 存储,我希望使它们尽可能相似)。
我已经尝试过 docker-compose 网络配置,但我似乎无法完成这项工作。
关于如何在 docker-compose 中解决这个问题有什么想法吗?
附加信息:
我已经尝试过host.docker.internal(和gateway.docker.internal)但无济于事。host.docker.internal解析为192.168.65.2,我可以使用该 IP 进行访问storage,app但从浏览器192.168.65.2:9000会超时。
但看来使用我的电脑的外部IP是可行的。如果我使用,192.168.3.177:9000我可以storage从app浏览器甚至外部设备进行访问(完美!)。然而,这个ip不是固定的,而且对于我的同事来说显然不一样,所以看来我需要的是一种在执行时动态分配它的方法docker-compose up
已经有一段时间了,但我想如果有人遇到类似的问题,我想分享一下我最终如何根据我的情况解决这个问题。相关XKCD
实用的解决方案
在花了相当长的时间让它只与 docker 一起工作(见下文)之后,我最终走上了实用的道路,并在 Django 方面修复了它。
由于我使用 Django Rest Framework 公开存储中对象的 url,因此我必须修补 Django Storages S3 后端创建的对象 url 的默认输出,以便在本地开发时交换主机。在内部,Django 使用 API 密钥直接连接到对象存储,但在外部,文件只能通过签名的 URL(私有存储桶)访问。并且由于主机名可以是签名内容的一部分,因此需要在生成签名之前正确设置它(否则主机名的脏查找和替换就足够了。)
我必须修补的三种情况:
我想使用当前请求的主机作为对象链接的主机(但在 Minio 的端口 9000 上)。这样做的优点是:
localhost、127.0.0.1、 以及分配给我的机器的任何 IP 地址。因此,我可以在我的机器上使用localhost并使用192.168.x.x手机上的地址进行测试,而无需更改代码。上述情况实施如下:
# dev settings, should be read from env for production etc.
AWS_S3_ENDPOINT_URL = 'http://storage:9000'
AWS_S3_DEV_ENDPOINT_URL = 'http://{}:9000'
def get_client_for_presigned_url(request=None):
# specific client for presigned urls
endpoint_url = settings.AWS_S3_ENDPOINT_URL
if request and settings.DEBUG and settings.AWS_S3_DEV_ENDPOINT_URL:
endpoint_url = settings.AWS_S3_DEV_ENDPOINT_URL.format(request.META.get('SERVER_NAME', 'localhost'))
storage = S3Boto3Storage(
endpoint_url=endpoint_url,
access_key=settings.AWS_ACCESS_KEY_ID,
secret_key=settings.AWS_SECRET_ACCESS_KEY,
)
return storage.connection.meta.client
class DownloadUrlField(serializers.ReadOnlyField):
# example usage as pre-signed download url
def to_representation(self, obj):
url = get_client_for_presigned_url(self.context.get('request')).generate_presigned_url(
"get_object",
Params={
"Bucket": settings.AWS_STORAGE_BUCKET_NAME,
"Key": str(obj.file_object), # file_object is key for object store
"ResponseContentDisposition": f'filename="{obj.name}"', # name is user readable filename
},
ExpiresIn=3600,
)
return url
# similar for normal url and pre-signed post
Run Code Online (Sandbox Code Playgroud)
这为我和其他开发人员提供了一个易于使用、本地、离线可用的开发对象存储,而只需少量签入代码。
替代解决方案
我很快发现,要在 docker 端修复它,我真正需要的是获取主机(而不是docker 主机)的 IP 地址,并使用它来创建到我的 Minio 存储的链接。正如我在问题中提到的,这与地址不同docker.host.internal。
解决方案:使用env变量传入主机ip。
docker-compose.yml
services:
app:
build: backend/
ports:
- "8000:8000"
environment:
HOST_IP: $DOCKER_HOST_IP
volumes:
- ./backend/src:/app/src
command: /usr/local/bin/python src/manage.py runserver 0.0.0.0:8000
# ... same as in question
Run Code Online (Sandbox Code Playgroud)
设置.py
AWS_S3_ENDPOINT_URL = f'http://{os.environ['HOST_IP']}:9000'
Run Code Online (Sandbox Code Playgroud)
DOCKER_HOST_IP当调用此方法时设置环境变量时docker-compose up,将创建使用该 IP 并正确签名的 url。获取环境变量到docker-compose的几种方法:
.bash_profile-e将其传递给带有标志的命令因为.bash_profile我使用了以下快捷方式:
alias myip='ifconfig | grep "inet " | grep -v 127.0.0.1 | cut -d\ -f2'
export DOCKER_HOST_IP=$(myip)
Run Code Online (Sandbox Code Playgroud)
对于 PyCharm(对于调试非常有用)来说,设置有点棘手,因为默认环境变量不能是动态的。但是,您可以为“运行配置”定义一个在“启动前”运行的脚本。我创建了一个命令,以与中相同的方式设置环境变量,.bash_profile并且奇迹般地,PyCharm 在运行 docker-compose 命令时保留了该环境,使其按照我想要的方式工作。
问题:
localhost,需要使用当前IP地址由于这些问题,我最终采用了实际的解决方案。
| 归档时间: |
|
| 查看次数: |
2729 次 |
| 最近记录: |