• 1 Post
  • 14 Comments
Joined 1 year ago
cake
Cake day: June 24th, 2023

help-circle

  • Containers can be based on operating systems that are different to your computer.

    Containers utilise the host’s kernel - which is why there needs to be some hoops to run Linux container on Windows (VM/WSL).

    That’s one of the most key differences between VMs and containers. VMs virtualise all the hardware, so you can have a totally different guest and host operating systems; whereas because a container is using the host kernel, it must use the same kind of operating system and accesses the host’s hardware through the kernel.

    The big advantage of that approach, over VMs, is that containers are much more lightweight and performant because they don’t have a virtual kernel/hardware/etc. I find its best to think of them as a process wrapper, kind of like chroot for a specific application - you’re just giving the application you’re running a box to run in - but the host OS is still doing the heavy lifting.


  • As always, it depends! I’m a big fan of “the right tool for the job” and I work in many languages/platforms as the need arises.

    But for my “default” where I’m building up the largest codebase, I’ve gone for the following:

    • TypeScript
      • Strongly-typed (ish) which makes for a nice developer experience
      • Makes refactoring much easier/less error-prone.
      • Runs on back-end (node) and front-end, so only one language, tooling, codebase, etc. for both.
    • SvelteKit
      • Svelte as a front-end reactive framework is so nice and intuative to use, definite the best there is around atm.
      • It’s hybrid SSR/CSR is amazing, so nice to use.
      • As the back-end it’s “OK”, needs a lot more work IMO, but I do like it for a lot of things - and can not use it where necessary.
    • Socket.IO
      • For any real-time/stream based communication I use this over plain web sockets as it adds so much and is so easy to use.
    • PostgreSQL
      • Really solid database that I love more and more the more I use it (and I’ve used it a lot, for a very long time now!)
    • Docker
      • Easy to use container management system.
      • Everything is reproducible, which is great for development/testing/bug-fixing/and disasters.
      • Single method to manage all services on all servers, regardless of how they’re implemented.
    • Traefik
      • Reverse proxy that can be set to auto-configure based on configuration data in my docker compose files.
      • Automatically configuring takes a pain point out of deploying (and allows me to fully automate deployment).
      • Really fast, nice dashboard, lots of useful middleware.
    • Ubuntu
      • LTS releases keep things reliable.
      • Commercial support available if required.
      • Enough name recognition that when asked by clients, this reassures them.


  • I was recently helping someone working on a mini-project to do a bit of parsing of docker compose files, when I discovered that the docker compose spec is published as JSON Schema here.

    I converted that into TypeScript types using JSON Schema to TypeScript. So I can create docker compose config in code and then just export it as yaml - I have a build/deploy script that does this at the end.

    But now the great thing is that I can export/import that config, share it between projects, extend configs, mix-in, and so on. I’ve just started doing it and it’s been really nice so far, when I get a chance and it’s stabilised a bit I’m going to tidy it up and share it. But there’s not much I’ve added beyond the above at the moment (just some bits to mix-in arrays, which was what set me off on this whole thing!)



  • Are there any good alternatives?

    We’ve started using Jitsi for video/screen-sharing and that’s going well so far - but it’s based very much around the “corporate meeting” concept, rather than “playing D&D with mates” or “online gaming with people”.

    Mumble is decent enough for voice comms, but of course lacks video, which for my friend group is a deal-breaker. While the audio quality is noticably better most of the time, its noise suppression is not as good as Discord. It does have text chat, but lacks the utility of Discord’s chat - which we use in D&D for sharing information, images, note-taking, etc.

    Things do game tracking/voice like Steam, Xbox Live, PSN, etc. but then each only supports their own platforms and services - whereas Discord is common to all.

    I think what DIscord does well is bring together a few really established, tried and tested technologies, under one roof and integrates them seamlessly. There is definitely value in that, and I would be really interested in an open source/self-hosted equivalent.

    My main concerns with Discord are:

    1. They inevitably ramp up income earning opportunities and therefore eventually compromise the system.
    2. It can’t be catalogued/searched easily.
    3. It seems like a near-perfect platform for harvesting data for ML (and the platform has some traction with the ML community already).



  • vampatori@feddit.uktoProgramming@beehaw.orgEmail is Dead
    link
    fedilink
    English
    arrow-up
    9
    ·
    1 year ago

    From a personal perspective, I absolutely agree - I only check my email when I’m specifically expecting something, which is rarely. But at work emails are still incredibly important.

    Are there any protocols/services designed specifically for one time codes? Receipts? I think something that’s dedicated to those kinds of tasks would be great from an ease-of-use perspective - no more messing about waiting for delivery, searching through hordes of emails, checking spam folder, etc.

    Another problem we have is the rise of oauth - the core idea is great, but the reality is that it ties a lot of people to these Big Tech services.



  • vampatori@feddit.uktoSelfhosted@lemmy.worldDefeated by NGINX
    link
    fedilink
    English
    arrow-up
    3
    ·
    edit-2
    1 year ago

    Assume nothing! Test every little assumption and you’ll find the problem. Some things to get you started:

    • Does the “app” domain resolve to the app container’s IP from within the nginx container?
    • Can you proxy_pass to the host:port directly rather than using an upstream definition? If not, what about IP:port?
    • Can you connect to the app container from outside (if exposed)? What about from inside the nginx container? What about inside the app container?
    • Is the http(s) connection to the server (demo.example.com) actually going to your nginx instance? Shut it down and see if it changes.
    • If it works locally on 80, can you get it to work on the VPS on 80?
    • Are you using the exact same docker-compose.yaml file for this as locally? If not, what’s different?
    • Are you building the image? If so, are you incrementing the version number of the build so it gets updated?
    • Is there a firewall running on the host OS? If so, is it somehow interfering? Disable it and see.

    While not a direct solution to your problem, I no longer manually configure my reverse proxies at all now and use auto-configuring ones instead. The nginx-proxy image is great, along with it’s ACME companion image for automatic SSL cert generation with certbot - you’ll be up and running in under 30 mins. I used that for a long time and it was great.

    I’ve since moved to using Traefik as it’s more flexible and offers more features, but it’s a bit more involved to configure (simple, but the additional flexibility means everything requires more config).

    That way you just bring up your container and the reverse proxy pulls meta-data from it (e.g. host to map/certbot email) and off it goes.




  • The issues with LLM’s for coding are numerous - they don’t produce good results in my experience, there’s plenty of articles on their flaws.

    But… they do highlight something very important that I think we as developers have been guilty of for decades… a large chunk of what we do is busy work; the model definitions, the api to wrap the model, the endpoint to expose the model, the client to connect to the endpoint, the ui that links to the client, the server-side validation, the client-side validation, etc. On and on… so much of it is just busy work. No wonder LLM’s can offer up solutions to these things so easily - we’ve all been re-inventing the wheel over and over and over again.

    Busy work is the worst and it played a big part in why I took a decade-long break from professional software development. But now I’m back running my own business and I’m spending significant time reducing busy work - for profit but also for my own personal enjoyment of doing the work.

    I have two primary high-level goals:

    1. Maximise reuse - As much as possible should be re-usable both within and between projects.
    2. Minimise definition - I should only use the minimum definition possible to provide the desired solution.

    When you look at projects with these in mind, you realise that so many “fundamentals” of software development are terrible and inherently lead to busy work.

    I’ll give a simple example… let’s say I have the following definition for a model of a simple blog:

    User:
      id: int generate primary-key
      name: string
    
    Post:
      id: int generate primary-key
      user_id: int foreign-key(User.id)
      title: string
      body: string
    

    Seems fairly straight-forward, we’ve all done this before - it can be in SQL, prisma, etc. But there’s some fundamental flaws right here:

    1. We’ve tightly coupled Post to User through the user_id field. That means Post is instantly far less reusable.
    2. We’ve forced an id scheme that might not be appropriate for different solutions - for example a blogging site with millions of bloggers with a distributed database backend may prefer bigint or even some form of UUID.
    3. This isn’t true for everything, but is for things like SQL, Prisma, etc. - we’ve defined the model in a data-definition language that doesn’t support many reusability features like importing, extending, mixins, overriding, etc.
    4. We’re going to have to define this model again in multiple places… our API that wraps the database, any clients that consume that API, any endpoints that serve that API up, in the UI, the validation, and so on.

    Now this is just a really simple, almost superficial example - but even then it highlights these problems.

    So I’m working on a “pattern” to help solve these kinds of problems, but with a reference implementation in TypeScript. Let’s look at the same example above in my reference implementation:

    export const user = new Entity({
        name: "User",
        fields: [
            new NameField(),
        ],
    });
    
    export const post = new Entity({
        name: "Post",
        fields: [
            new NameField("title", { maxLength: 100 }),
            new TextField("body"),
        ],
    });
    
    export const userPosts = new ContentCreator({
        name: "UserPosts",
        author: user,
        content: post,
    });
    
    export const blogSchema = new Schema({
        relationships: [
            userPosts,
        ],
    });
    

    So there’s several things to note:

    1. Entities are defined in isolation without coupling to each other.
    2. We have sane defaults, no need to specify an id field for each entity (though you can).
    3. You can’t see it here because of the above, but there are abstract id field definitions: IDField and AutoIDField. It’s the specific implementation of this schema where you specify the type of ID you want to use, e.g. IntField, BigIntField, UUIDField, etc.
    4. Relationships are defined separately and used to link together entities.
    5. Relationships can bestow meaning - the ContentCreator relationship just extends OneToMany, but adds meta-data from which we can infer things in our UI, authorization, etc.
    6. Fields can be extended to provide meaning and to abstract implementations - for example the NameField extends TextField, but adds meta-data so we know it’s the name of this entity, and that it’s unique, so we can therefore have UI that uses that for links to this entity, or use it for a slug, etc.
    7. Everything is a separately exported variable which can be imported into any project, extended, overridden, mixed in, etc.
    8. When defining the relationship we sane defaults are used so we don’t need to explicitly define the entity fields we’re using to make the link, though we can if we want.
    9. We don’t need to explicitly add both our entities and relationships to our schema (though we can) as we can infer the entities from the relationships.

    There is another layer beyond this, which is where you define an Application which then lets you specify code generation components that to do all the busy work for you, settings like the ID scheme you want to use, etc.

    It’s early days, I’m still refining things, and there is a ton of work yet to do - but I am now using it in anger on commercial projects and it’s saving me time - generating types/interfaces/classes, database definitions, api’s, end points, ui components, etc.

    But it’s less about this specific implementation and more about the core idea - can we maximise reuse and minimise what we need to define for a given solution?

    There’s so many things that come off the back of it - so much config that isn’t reusable (e.g. docker compose files), so many things that can be automatically determined based on data (e.g. database optimisations), so many things that can be abstracted (e.g. deployment/scaling strategies).

    So much busy work that needs to be eliminated, allowing us to give LLM’s a run for their money!