You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Cloud Formation管理实例中,如何用EBS/EFS在docker-compose绑定Django代码卷?

在CloudFormation+Docker Swarm中挂载EBS/EFS存储到Django服务

我来帮你拆解这个问题,分EFS和EBS两种场景给你具体操作步骤,毕竟这俩AWS存储在Docker Swarm里的用法差异不小:

一、用EFS(多节点共享首选)

EFS是AWS的分布式共享存储,适合Docker Swarm多节点集群,所有节点都能访问同一份Django代码,步骤如下:

  1. 通过CloudFormation创建EFS资源
    在你的CloudFormation模板里定义EFS文件系统和挂载目标:

    Resources:
      DjangoEFS:
        Type: AWS::EFS::FileSystem
        Properties:
          PerformanceMode: generalPurpose
      EFSMountTarget:
        Type: AWS::EFS::MountTarget
        Properties:
          FileSystemId: !Ref DjangoEFS
          SecurityGroups: [!Ref EFSSecurityGroup]  # 允许NFS 2049端口访问
          SubnetId: !Ref SwarmNodeSubnet  # 和Swarm节点在同一个子网
    

    安全组要开放**入站NFS(2049端口)**给Swarm节点的安全组。

  2. 在Swarm节点自动挂载EFS
    在CloudFormation的EC2实例(Swarm管理/工作节点)的UserData里添加挂载命令,启动时自动挂载:

    #!/bin/bash
    mkdir -p /mnt/efs/django-code
    mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 ${EFS_DNS_NAME}:/ /mnt/efs/django-code
    # 写入fstab确保重启后自动挂载
    echo "${EFS_DNS_NAME}:/ /mnt/efs/django-code nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0" >> /etc/fstab
    

    这里的${EFS_DNS_NAME}可以通过CloudFormation的!GetAtt DjangoEFS.DnsName传递。

  3. 上传Django代码到EFS
    挂载完成后,你可以通过scp把本地代码传到Swarm节点的/mnt/efs/django-code目录,或者直接在节点上git clone你的项目仓库。

  4. 在docker-compose.yml中绑定卷
    直接用bind挂载,把EFS的本地挂载目录映射到容器内的Django代码目录:

    version: '3.8'
    services:
      django-app:
        image: python:3.11-slim
        volumes:
          - /mnt/efs/django-code:/app  # 本地EFS目录 -> 容器内代码目录
        working_dir: /app
        command: ["python", "manage.py", "runserver", "0.0.0.0:8000"]
        ports:
          - "8000:8000"
    

    部署栈时执行docker stack deploy -c docker-compose.yml django-stack即可,Swarm所有节点都能访问这份共享代码。

二、用EBS(单节点场景)

EBS是单AZ的块存储,只能挂载到单个EC2实例,适合单节点Swarm或不需要多节点共享代码的场景:

  1. CloudFormation创建并附加EBS卷
    在模板里定义EBS卷并附加到Swarm管理节点:

    Resources:
      DjangoEBSVolume:
        Type: AWS::EC2::Volume
        Properties:
          AvailabilityZone: !GetAtt SwarmManagerInstance.AvailabilityZone
          Size: 20  # 根据代码大小调整
          VolumeType: gp3
      EBSVolumeAttachment:
        Type: AWS::EC2::VolumeAttachment
        Properties:
          InstanceId: !Ref SwarmManagerInstance
          VolumeId: !Ref DjangoEBSVolume
          Device: /dev/xvdf
    
  2. 格式化并挂载EBS到节点
    同样在Swarm节点的UserData里添加格式化和挂载命令(第一次挂载需要格式化):

    #!/bin/bash
    mkdir -p /mnt/ebs/django-code
    # 检查是否已格式化,避免重复格式化
    if ! blkid /dev/xvdf; then
      mkfs.ext4 /dev/xvdf
    fi
    mount /dev/xvdf /mnt/ebs/django-code
    # 写入fstab
    echo "/dev/xvdf /mnt/ebs/django-code ext4 defaults 0 0" >> /etc/fstab
    
  3. 上传Django代码
    把代码传到/mnt/ebs/django-code目录即可。

  4. docker-compose.yml配置(加节点约束)
    因为EBS只挂载在单个节点,必须约束Swarm服务只能调度到这个节点:

    version: '3.8'
    services:
      django-app:
        image: python:3.11-slim
        volumes:
          - /mnt/ebs/django-code:/app
        working_dir: /app
        command: ["python", "manage.py", "runserver", "0.0.0.0:8000"]
        ports:
          - "8000:8000"
        deploy:
          placement:
            constraints: [node.hostname == swarm-manager-01]  # 替换成你的节点 hostname
    

关键注意事项

  • 权限问题:确保容器内的用户(比如www-data或python用户)对挂载目录有读写权限,必要时在容器启动前执行chown命令。
  • Swarm集群场景优先EFS:如果你的Swarm有多个工作节点,EBS无法跨节点共享代码,会导致不同节点上的容器访问到不同的代码版本,EFS是共享存储,能避免这个问题。
  • CloudFormation权限:确保EC2实例的IAM角色有elasticfilesystem:ClientMount、ec2:AttachVolume等相关权限,否则挂载会失败。

内容的提问来源于stack exchange,提问作者Naitik Shah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:20:43