I’ve been writing code professionally for 24 years, 15 of which has been Python and 9 years of that with Docker. I got tired of running into the same complications every time I started a new job, so I wrote this. Maybe you’ll find it useful, or it could even start a conversation, but this post has been a long time coming.

Update: I had a few requests for a demo repo as a companion to this post, so I wrote one today. It includes a very small Django demo user Docker, Compose, and GitLab CI.

  • jacksilver@lemmy.world
    link
    fedilink
    arrow-up
    8
    ·
    1 month ago

    Hey OP, it looks like you’re the author of the post? If so I’m curious how you handle cloud services like AWS or Azure when taking this approach? One of the major issues I’ve run into when working with teams is how to test or evaluate against cloud services without creating an entire infrastructure in the cloud for testing.

    • Daniel Quinn@lemmy.caOP
      link
      fedilink
      English
      arrow-up
      8
      ·
      1 month ago

      It’s a tough one, but there are a few options.

      For AWS, my favourite one is LocalStack, a Docker image that you can stand up like any other service and then tell it to emulate common AWS services: S3, Lamda, etc. They claim to support 80 different services which is… nuts. They’ve got a strange licensing model though, which last time I used it meant that they support some of the more common services for free, but if you want more you gotta pay… and they aren’t cheap. I don’t know if anything like this exists for Azure.

      The next-best choice is to use a stand-in. Many cloud services are just managed+branded Free software projects. RDS is either PostgreSQL or MySQL, ElastiCache is just Redis, etc. For these, you can just stand up a copy of the actual service and since the APIs are identical, you should be fine. Where it gets tricky is when the cloud provider has messed with the API or added functionality that doesn’t exist elsewhere. SQS for example is kind of like RabbitMQ but not.

      In those cases, it’s a question of how your application interacts with this service. If it’s by way of an external package (say Celery to SQS for example), then using RabbitMQ locally and SQS in production is probably fine because it’s Celery that’s managing the distinction and not you. They’ve done the work of testing compatibility, so theoretically you don’t have to.

      If however your application is the kind of thing that interacts with this service on a low level, opening a direct connection and speaking its protocol yourself, that’s probably not a good idea.

      That leaves the third option, which isn’t great, but I’ve done it and it’s not so bad: use the cloud service in development. Normally this is done by having separate services spun up per user or even with a role account. When your app writes to an S3 bucket locally, it’s actually writing to a real bucket called companyname-username-projectbucket. With tools like Terraform, the fiddly process of setting all this up can be drastically simplified, so it’s not so bad – just make sure that the developers are aware of the fact that their actions can incur costs is all.

      If none of the above are suitable, then it’s probably time to stub out the service and then rely more heavily on a QA or staging environment that’s better reflective of production.

      • jacksilver@lemmy.world
        link
        fedilink
        arrow-up
        3
        ·
        1 month ago

        I appreciate the response!

        I’ve definitely used tools like LocalStack before and when it works it’s great, but sadly doesn’t usually provide a 1-to-1 replacement.

        Seeing your different approaches is helpful and I will have to see what elements I can pull into my current projects!

    • Daniel Quinn@lemmy.caOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      edit-2
      1 month ago

      High praise! Just keep in mind that my blog is a mixed bag of topics. A little code, lots of politics, and some random stuff to boot.

      • ALERT@sh.itjust.works
        link
        fedilink
        English
        arrow-up
        3
        ·
        1 month ago

        from my 15 years of RSS experience, a typical feed contains not much more than 5% of useful information, so I am prepared for filtering, no worries :)

  • __init__@programming.dev
    link
    fedilink
    arrow-up
    2
    ·
    1 month ago

    Nice. You should check out devcontainers if you haven’t already. Maybe it deviates a little from the dev/prod parity idea, but you can use it with a compose file like you described. It’s saved my current team quite a bit of headache in maintaining local dev environments and keeping everyone in sync as the project evolves.

  • onlinepersona@programming.dev
    link
    fedilink
    English
    arrow-up
    1
    ·
    1 month ago

    I either missed it or it isn’t in the “developer tools” section: how do you connect this to an IDE or editor with an LSP or DAP? The image might have python:3.12 but locally you only have python:3.6 mind you, so it’s not something one can ignore. How do you handle this?

    Anti Commercial-AI license

    • dallen@programming.dev
      link
      fedilink
      arrow-up
      2
      ·
      1 month ago

      In VS code these should work through the Remote-Containers flow, just like they do through Remote-SSH.

  • sip@programming.dev
    link
    fedilink
    arrow-up
    1
    ·
    edit-2
    1 month ago

    are you me?

    instead of that partial thing at the top I extend a base one into web, worker, test and build (simulate CI step).

  • Martín@lemmy.world
    link
    fedilink
    arrow-up
    1
    arrow-down
    1
    ·
    1 month ago

    It is not realistic to replicate a production setup in development when you’re working with sensitive user data. I’ve worked in different contexts (law enforcement, healthcare, financial services) where we’ve had complicated setups (in one instance including a thing called pre-staging environment), but never would a sizeable team of developers have access to user data, and thus to a realistic setup in terms of size, let alone of quality of data.

    • Daniel Quinn@lemmy.caOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      1 month ago

      It sounds like you’re confusing the application with the data. Nothing in this model requires the use of production data.

      • Martín@lemmy.world
        link
        fedilink
        arrow-up
        1
        arrow-down
        1
        ·
        1 month ago

        Just trying not so confuse realistic testing with self-deception :) Not convinced testing with synthetic data can pretend to be similar to a production environment.

        • Daniel Quinn@lemmy.caOP
          link
          fedilink
          English
          arrow-up
          1
          ·
          1 month ago

          But there’s nothing stopping you from loading realistic (or even real) data into a system like this. They’re entirely different concepts. Indeed, I’ve loaded gigabytes of production data into systems similar to what I’m proposing here (taking all necessary precautions of course). At one company, I even built a system that pulled production into a developer-friendly snapshot while simultaneously pseudo-anonymising that data so it can be safely (for some value of ${safe}) be tinkered with in development.

          In fact, adhering to a system like this makes such things easier, since you don’t have to make any concessions to “this is how we do it in development”. You just pull a snapshot from the environment you want to work with and load it into your Compose session.