Live data from Hacker News

The simplicity of single-file Golang deployments

amazingcto.com

21–30 of 232 posts

Re: The simplicity of single-file Golang deployments

#21

Earlier quoted context omitted.

You can definitely pack a Java application into a single JAR file and skip the Docker. Java's xenophobia (allergy to linking libraries) is the real root of "write once run everywhere" so often all you need is the Java runtime.

You still need jre so it's not really a "single file" like on Go

You still need a bespoke systemd configuration for TFA's Go deploys so it's not really a "single file" deploy their either.

And like the sibling comment noted, once you're allowed to set up the machine to support easy depolyment (e.g. JRE, Tomcat), a WAR becomes a single file deploy.

Re: The simplicity of single-file Golang deployments

#22

From the article: "Standing here it looks like Docker was invented to manage dependencies for Python, Javascript and Java. It looks strange from a platform that deploys as one single binary." Let me say the quiet part out loud: Docker is covering up the fact that we don't write deployable software any more. Go isn't perfect either. The author isn't dealing with assets (images anyone?). I think there is plenty of room…

Anymore? When were we writing "deployable" software in the past?

Re: The simplicity of single-file Golang deployments

#23

I feel docker in many cases is a hack for languages and runtimes that don’t support single file static linked binaries. Often a single binary is a simpler and better option instead of a docker container.

I more view it as us recognizing that there's more to "a system" than a binary. Kubernetes is this concept taken to its conclusion (since it defines everything in code, literally everything). But docker is often a super convenient middle ground where it's not nearly as stupidly verbose to just get a simple thing running, but still checks a lot of the boxes.

I used to feel similarly with Java. "Why," I asked, "would you need this docker thing? Just build the shaded JAR and off you go."

And to be sure, there are some systems - especially the kind people seem to build in go (network-only APIs that never touch the fs and use few libraries) - that do not need much more than their binary to work. But what of systems that call other CLI utilities? What of systems that create data locally that you'd like to scoot around or back up?

Eventually nearly every system grows at least a few weird little things you need to do to set it up and make it comfy. Docker accommodates that.

I do think there's a big kernel of truth to your sentiment though - I loved rails as a framework but hated, just hated deploying it, especially if you wanted 2 sites to share a linux box. Maybe I was just bad at it but it was really easy to break BOTH sites. Docker has totally solved this problem. Same for python stuff.

I do think docker is also useful as a way to make deploying ~anything all look exactly the same. "Pull image, run container with these args". I actually think this is what I like the most about it - I wrote my own thing with the python docker SDK, basically a shitty puppet/ansible, except it's shitty in the exact way I want it to be. And this has been the best side effect - I pay very little in resource overhead and suddenly now all my software uses the exact same deployment system.

Re: The simplicity of single-file Golang deployments

#24
post #9

How does one handle zero downtime deployments with single-file golang binaries? I remember I tried this setup some time ago and I couldn't successfully manage cleanly to accomplish no downtime when deploying a new version of my service. The reason was mainly port reuse. I couldn't have the old and the new version of my service running on the same port... so I started to hack together something and it became dirty pre…

Some of this is solved by using e.g. systemd, depending on your needs.

> I couldn't have the old and the new version of my service running on the same port...

You can, actually! You just can’t open the port twice by default. So one or both of the processes needs to inherit the port from a parent process, get passed the port over a socket (Unix sockets can transmit file descriptors), or use SO_REUSEADDR.

There are some libraries that abstract this, and some of this is provided by tools like systemd.

Some of this is probably going to have to be done in your application—like, once your new version starts, the old version should stop accepting new connections and finish the requests it has already started.

Re: The simplicity of single-file Golang deployments

#25
post #14

When I was stuck doing a web application in Java 15 years ago, I hated everything about it except for the deployment story, which boiled down to a single .war file being pushed to the server. When we upgraded to Perl, I liked that system so we designed deployment around "PAR" files in a similar way, bundling all of the dependencies together with the application in the CI build process, and I wrote a tiny bit of infra…

> I don't see what's special or better about compiling everything into a single binary, apart from fetishizing the executable format.

When you distribute your software to other people, it cuts the step of installing the correct interpreter... at the cost of requiring the correct computer architecture.

It is very likely a gain.

Re: The simplicity of single-file Golang deployments

#27

From the article: "Standing here it looks like Docker was invented to manage dependencies for Python, Javascript and Java. It looks strange from a platform that deploys as one single binary." Let me say the quiet part out loud: Docker is covering up the fact that we don't write deployable software any more. Go isn't perfect either. The author isn't dealing with assets (images anyone?). I think there is plenty of room…

Anymore? When were we writing "deployable" software in the past?

You used to buy a disk, put it on your computer and run the thing there.

Re: The simplicity of single-file Golang deployments

#28

From the article: "Standing here it looks like Docker was invented to manage dependencies for Python, Javascript and Java. It looks strange from a platform that deploys as one single binary." Let me say the quiet part out loud: Docker is covering up the fact that we don't write deployable software any more. Go isn't perfect either. The author isn't dealing with assets (images anyone?). I think there is plenty of room…

I'm unsatisfied with the current situation too, but it's a hard problem. You can either go full container (which means no BSD, and having to deal with Docker or Kubernetes and all the associated woes), or fallback to native packages which are a huge PITA to build, deploy and use.

I think that Nix and Guix have part of the solution: have a way to build fully independent packages that can be easily installed. But I'm not comfortable with the complexity of Nix, and Guix does not run on FreeBSD. And ultimately you still have to handle distribution and configuration of the base system you deploy on.

Innovation is possible, but there are a lot of expectations for any system dealing with building and deploying software. I feel that there are fundamental limitations inherited from the way UNIX OS work, and I wish we had lower level operating systems focused on executing services on multiple machines in a way similar to how mainframes work. One can dream.

Re: The simplicity of single-file Golang deployments

#29

From the article: "Standing here it looks like Docker was invented to manage dependencies for Python, Javascript and Java. It looks strange from a platform that deploys as one single binary." Let me say the quiet part out loud: Docker is covering up the fact that we don't write deployable software any more. Go isn't perfect either. The author isn't dealing with assets (images anyone?). I think there is plenty of room…

Assets of any kind can be embedded in the executable and accessed via the embed.FS interface. This makes it trivial to bundle up all dependencies if desired.

Re: The simplicity of single-file Golang deployments

#30
post #9

How does one handle zero downtime deployments with single-file golang binaries? I remember I tried this setup some time ago and I couldn't successfully manage cleanly to accomplish no downtime when deploying a new version of my service. The reason was mainly port reuse. I couldn't have the old and the new version of my service running on the same port... so I started to hack together something and it became dirty pre…

Some of this is solved by using e.g. systemd, depending on your needs. > I couldn't have the old and the new version of my service running on the same port... You can, actually! You just can’t open the port twice by default. So one or both of the processes needs to inherit the port from a parent process, get passed the port over a socket (Unix sockets can transmit file descriptors), or use SO_REUSEADDR. There are som…

So can I just start another process with SO_REUSEADDR and gracefully shutdown the old process?

The master/worker thing that nginx / gunicorn et al do is pretty neat, but relies on signals; so seems pretty messy and error prone to write yourself.

Post reply on HN