Skip to content
This repository has been archived by the owner on Sep 7, 2018. It is now read-only.

Create alpine based container #44

Closed
DavidJFelix opened this issue Jun 9, 2016 · 29 comments
Closed

Create alpine based container #44

DavidJFelix opened this issue Jun 9, 2016 · 29 comments

Comments

@DavidJFelix
Copy link

Alpine linux seems to be the direction of the docker community with respect to reducing image size.
It might be nice to have a grafana/grafana:alpine tag, like most official repos have.

@jangaraj
Copy link
Contributor

jangaraj commented Jun 9, 2016

I don't see reason why it should be additional tag. It should be used as a standard base OS image. Feel free to create PR :-)

@DavidJFelix
Copy link
Author

Alpine comes with its own bundle of surprises. While it seems like eventually running alpine will be default for most docker containers, even the official ones typically use debian for the default and require using the :alpine tag for the lighter container that may have less interactive tooling than people are used to.

@jangaraj
Copy link
Contributor

jangaraj commented Jun 9, 2016

The main problem of alpine is that it uses musl instead of standard glibc library. But you can compile golang statically, so I don't see any problem for Grafana with musql lib. Actually check forks and you will find alpine versions there. Only somebody should to create generic Docker image.

@DavidJFelix
Copy link
Author

@jangaraj there's a docker golang:alpine tag that could be used as a base, but this would require building from source, while the current dockerfile is pulling a deb.

@jangaraj
Copy link
Contributor

jangaraj commented Jun 9, 2016

No, you don't need golang:alpine (golang is required only for compilation, not for execution) - check this fork https://github.com/appcelerator/docker-grafana

@DavidJFelix
Copy link
Author

I agree; just to clarify though, I was suggesting we use alpine's version of go to compile grafana, which should not be difficult. In fact, the linked example does that, despite being based on alpine rather than golang:alpine:

https://github.com/appcelerator/docker-grafana/blob/master/Dockerfile#L11

The only reason I suggested basing it on golang is because I think it's the largest dep, so putting it at an earlier step can improve image build speed (this isn't really something worth optimizing heavily). There may be issues if golang:alpine doesn't use apk and instead compiles to source, as it would be harder, so it's probably wise to use alpine directly rather than golang:alpine.

@jangaraj
Copy link
Contributor

You can save ~1 minute in Docker build process by using golang:alpine or
70MB of virtual size (virtual size of golang:alpine - alpine) per download by using pure alpine image. Optimization for build speed makes sense in case when your build process (~developer time) is more expensive than storage. Then is better option to create dedicated Dockerfile only for build (CI) process. Production Docker image should have the smallest possible size - that's use case for alpine.

@DavidJFelix
Copy link
Author

I imaging that if you used golang:alpine, you'd still do the apk removal of go to slim up the container at the end.

@jangaraj
Copy link
Contributor

Yes, you can use apk removal, but it didn't reduce final image size (see how Docker storage drivers/layers/copy-on-write works). You can use additional flattening of final image, but it will need additional build time/tool as well.

@alkersan
Copy link

alkersan commented Jul 9, 2016

Hi @DavidJFelix and @jangaraj. I've spent some time tinkering with grafana and musl libc and have few thoughts.

  • As far as I understand Grafana uses PhantomJS for server side rendering (probably when sharing plots). In current state PhantomJS doesn't work with musl. Even with glibc compatibility packages I couldn't make it launch. Probably some day it will happen to work, but for now it's blocked by few upstream (primarily WebKit's) issues. Thus it's technically not possible right now to make functionally equivalent Grafana docker image based on alpine.
  • I've compiled Grafana server itself with musl and it don't seem to have any problems. Both dynamic and static linking worked for me. Prebuilt distributions (few recently released versions) can be found here. PhantomJs was removed, and only server binaries and web assets packed inside.
  • Eventually I'd like to see statically linked grafana distributions in official repositories, just like influxdb does: not only docker image is published, but also prebuilt statically linked distributions available (like this 0.12 and this 0.13). This way it becomes much easier to build custom images, without touching sources.

@jangaraj
Copy link
Contributor

jangaraj commented Jul 9, 2016

Good job @alkersan.

You should to ask Raintank guys for static builds (probably the best option is Slack).

@torkelo
Copy link
Member

torkelo commented Jul 11, 2016

I had some issues trying to do a static build due to cgo usage (for sqlite3) that did not work in static build, but that might have changed.

@alkersan
Copy link

@torkelo what libc did you use? musl or glibc?

@torkelo
Copy link
Member

torkelo commented Jul 11, 2016

It was a long time ago that I tried to create a static binary with no runtime glibc dependency, but I failed as the cgo or sqlite3 issue did have issues with static linking, not sure if that has been resolved or not.

@alkersan
Copy link

@torkelo I've just tried to build with static linking on desktop linux (with glibc). The resulting server binary isn't functional. It fails to perform sqlite migrations on start. As far as I know it's tricky to make static linking with glibc. On the other hand, musl-libc was created to be linkable statically. Artifacts that I've built previously were made in alpine environment and linked musl-libc.
I haven't done thorough testing of functionality. Just started server, added in-house influxdb and imported few dashboards.

@syepes
Copy link

syepes commented Aug 8, 2016

+1 For statically linked releases, @alkersan thanks for the sharing your builds

@adipirro
Copy link

adipirro commented Nov 2, 2016

fpm added apk support in this pull request

My initial attempts at using it have resulted in unusable archives (also takes ~1 hour to build). Poking around a bit to see what I'm doing wrong. Will also take a look at the builds from @alkersan

@adipirro
Copy link

adipirro commented Nov 3, 2016

Gave up on using fpm for now...took too long and was hard to debug.

Using @alkersan's work as a base, I've put together a sample image for you guys to try out.

Sample Image: https://hub.docker.com/r/adipirro852/grafana/

Check the linked PR for the Dockerfile.

I forked alkersan/grafana-musl in order to create a statically compiled distribution for 3.1.1. I also added a bit more documentation to the build process.

Current Build Repo: https://github.com/adipirro/grafana-musl
Current Build Releases: https://github.com/adipirro/grafana-musl/releases

The main thing that needs to happen is for the musl build to make its way into the normal release process. Not sure who needs to make that happen, but feel free to use the code above as a base.

Once that is done I can modify my PR to pull the official distribution and change the scripts to push a grafana/grafana:alpine image.

Oh...and almost forgot. The alpine based container checks in at a cool 52.13 MB. Compare that to the existing image which clocks in at 260.6 MB.

@DavidJFelix
Copy link
Author

DavidJFelix commented Nov 4, 2016

@adipirro one thing that you may want to look into is that there are several people bundling glibc into their alpine containers manually. I'm not sure how I feel about this practice yet, but it may be worth investigating.

Package Repo
Repo using example (note, sgerrand is the new maintainer, not andyshinn in this code)

IMO:

Pros:

  • Migration might be easier
  • No musl/glibc weirdness that has to be accounted for

Cons:

  • Manually installing libc into a container which is explicitly designed around a different libc implementation and suggests chroot as a means of support (this con should sound pretty bad, from an ops standpoint, when you read it)
  • "Untrusted" apk. You have to set "allow untrusted" to install that apk; treat it as such.

@DavidJFelix
Copy link
Author

@adipirro looking at what you've got -- it looks like you've got it figured out the safer way, making my suggestion less of a good idea. I figured I'd leave it there for posterity though.

@adipirro
Copy link

adipirro commented Nov 4, 2016

@DavidJFelix Huh...it seems less than ideal, but useful in cases where you don't really have a way around it.

I'll try building a container with the standard release offered on the download page and see how that goes.

@adipirro
Copy link

adipirro commented Nov 4, 2016

Well...it worked! As soon as I have a chance I'll update my PR/image to give an example of this method as well.

Oh...and PhantomJS still doesn't work :/

@DavidJFelix
Copy link
Author

It seems like the issue mentioned may actually be a result of glibc-expecting packages also expecting other libraries which aren't present. The reason glibc gets all the attention is that you can dynamically link against it and legally license your code outside of the GPL, but statically it requires your code to be GPL, which is a non starter for most people. Alpine doesn't really have anything against glibc aside from being a little larger than musl, the benefit of musl is that it is designed to be statically compiled, which is one of the goals of alpine. If Phantom (or other programs) are dynamically linked with multiple libraries they expect, you're going to have issues with each one, not just glibc. It seems like phantom is (in general) one of the largest headaches as it doesn't agree with musl and is dynamically linked against a number of libraries.

@adipirro
Copy link

adipirro commented Nov 4, 2016

Uploaded a new tag for the image using alpine-pkg-glibc.

adipirro852/grafana:alpine-glibc Dockerfile

Size of this image: 126.9 MB
PhantomJS Contribution: 64.8 MB
Alpine-pkg-glibc Contribution: 9 MB

If it is possible to get rid of the phantomjs dependency...that would probably be the way to go. It is a large dependency and a general PITA to get working with musl. Also, since it seems to only be used for rendering static png files on the server...I think a non-phantomjs method could be found.

We'd still need to statically compile with musl or use alpine-pkg-glibc for the cgo dependency, but I think those are reasonable options to choose from once the phantomjs issue is sorted out.

@SimenB
Copy link

SimenB commented May 23, 2017

You can build in one image, and copy over the artefact to another to maintain a slim size.
https://docs.docker.com/engine/userguide/eng-image/multistage-build/

@kneal
Copy link

kneal commented Aug 3, 2017

What's the status on this being resolved?

@DavidJFelix
Copy link
Author

@nac2791 I think it's being deferred until dependencies have better options for alpine.

@iotgopher
Copy link

+1 on alpine image

@xlson
Copy link
Contributor

xlson commented Apr 13, 2018

I'm closing this for now. We may very well create an alpine image in the future but it's not on the roadmap at this time.

Please like this issue if you're interested so that we can keep an eye on the demand for an alpine image.

@xlson xlson closed this as completed Apr 13, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants