diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..aadb3b4 --- /dev/null +++ b/README.adoc @@ -0,0 +1,73 @@ += docker-alpine + +:ao: alpinelinux.org +:hubp: _/alpine +:hub: https://hub.docker.com/r/{hubp}/ + +image:https://img.shields.io/docker/stars/{hubp}.svg[link={hub}] +image:https://img.shields.io/docker/pulls/{hubp}.svg[link={hub}] + +The official Docker image for https://{ao}[Alpine Linux]. +The image is only 5MB and has access to a package repository that is much more featureful than other BusyBox based images. + +== Why +Docker images today are big. +Usually much larger than they need to be. +There are a lot of ways to make them smaller, but the Docker populace still jumps to the `ubuntu` base image for most projects. +The size savings over `ubuntu` and other bases are huge: +[source] +---- +REPOSITORY TAG IMAGE ID CREATED SIZE +alpine latest cbc475bbc33b 55 seconds ago 5.53MB +ubuntu latest d131e0fa2585 7 days ago 102MB +debian latest 2d337f242f07 5 weeks ago 101MB +centos latest 9f38484d220f 7 weeks ago 202MB +---- +There are images such as `progrium/busybox` which get us close to a minimal container and package system, but these particular BusyBox builds piggyback on the OpenWRT package index, which is often lacking and not tailored towards generic everyday applications. +Alpine Linux has a much more featureful and up to date https://pkgs.{ao}[Package Index]: +[source] +---- +$ docker run progrium/busybox opkg-install nodejs +Unknown package 'nodejs'. +Collected errors: + * opkg_install_cmd: Cannot install package nodejs. + +$ docker run alpine apk add --no-cache nodejs +fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/main/x86_64/APKINDEX.tar.gz +fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz +(1/7) Installing ca-certificates (20190108-r0) +(2/7) Installing c-ares (1.15.0-r0) +(3/7) Installing libgcc (8.3.0-r0) +(4/7) Installing http-parser (2.8.1-r0) +(5/7) Installing libstdc++ (8.3.0-r0) +(6/7) Installing libuv (1.23.2-r0) +(7/7) Installing nodejs (10.14.2-r0) +Executing busybox-1.29.3-r10.trigger +Executing ca-certificates-20190108-r0.trigger +OK: 31 MiB in 21 packages +---- +This makes Alpine Linux a great image base for utilities, as well as production applications. +https://www.{ao}/about/[Read more about Alpine Linux here] and it will become obvious how its mantra fits in right at home with Docker images. + +NOTE: All of the example outputs above were last generated/updated on May 3rd 2019. + +== Usage +Stop doing this: +[source, docker] +---- +FROM ubuntu-debootstrap:14.04 +RUN apt-get update -q \ + && DEBIAN_FRONTEND=noninteractive apt-get install -qy mysql-client \ + && apt-get clean \ + && rm -rf /var/lib/apt +ENTRYPOINT ["mysql"] +---- +This took 28 seconds to build and yields a 169 MB image. +Start doing this: +[source, docker] +---- +FROM alpine:3.9 +RUN apk add --no-cache mysql-client +ENTRYPOINT ["mysql"] +---- +Only 4 seconds to build and results in a 41 MB image! diff --git a/README.md b/README.md deleted file mode 100644 index 62efce0..0000000 --- a/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# docker-alpine - -[![Docker Stars](https://img.shields.io/docker/stars/library/alpine.svg)][hub] -[![Docker Pulls](https://img.shields.io/docker/pulls/library/alpine.svg)][hub] - - -[hub]: https://hub.docker.com/r/gliderlabs/alpine/ diff --git a/docs/about.adoc b/docs/about.adoc new file mode 100644 index 0000000..6a018b8 --- /dev/null +++ b/docs/about.adoc @@ -0,0 +1,29 @@ += About + +https://alpinelinux.org[Alpine Linux] is a lightweight Linux distribution based on the https://www.musl-libc.org[musl libc] and https://busybox.net/[BusyBox]. +The base is extremely small, builds as a Docker image in a matter of seconds, and has a full-featured package index. + +== Musl Libc +Musl is consistent and provides high implementation quality regardless of whether the user is a tiny embedded system or a full-fledged server. +Minimal machine-specific code means less chance of breakage on minority architectures and better success with “write once run everywhere” C development. +Designed from the ground up for static linking, musl carefully avoids pulling in large amounts of code or data that the applications will not use. + +Using musl maximizes application deployability. +Binaries statically linked with musl have no external dependencies, even for features like DNS lookups or character set conversions that are implemented with dynamic loading on glibc. +An application truly can be deployed as a single binary file and run on any machine with the appropriate instruction set architecture and Linux kernel or Linux syscall ABI emulation layer. + +== BusyBox +BusyBox combines tiny versions of many common UNIX utilities into a single small executable. +It provides replacements for most of the utilities you usually find in GNU fileutils, shellutils, etc. +The utilities in BusyBox generally have fewer features than their full-featured GNU cousins. +However, the otions that *are* included provide the expected functionality and are tuned to behave like their GNU counterparts. +BusyBox provides a fairly complete environment for any small or embedded system. + +BusyBox has been written with size-optimization and limited resources in mind. +It is also extremely modular so you can easily include or exclude commands (or features) at compile time. +This makes it easy to customize your embedded systems. +To create a working system, just add some device nodes in `/dev`, a few configuration files in `/etc`, and a Linux kernel. + +== Match made in heaven +Pairing musl libc with BusyBox to combine common UNIX utilities into a single small executable, it makes for an excellent Docker image base. +We get extremely small builds (the base image is only 5 MB) that end up cutting time during push and pull. diff --git a/docs/build.adoc b/docs/build.adoc new file mode 100644 index 0000000..69f1582 --- /dev/null +++ b/docs/build.adoc @@ -0,0 +1,13 @@ += Build + +Normally, it is sufficient to simply run `docker pull alpine:tag` to get a locally cached image. +However, you can use the scripts present in this repository to build your own local copies. + +== Automatic +You can use `prepare-branch.sh` in order to generate the tarballs and Dockerfiles necessary to create an Alpine image for all of the supported architectures. +Simply decide which release of alpine you wish to be able to build (such as `v3.9` or `edge`) and call the `prepare` function of `prepare-branch.sh`. +For example, to generate edge images, you would run `prepare-branch.sh prepare edge`. +This will create a directory under `/tmp`, download release tarballs for the selected version, generate necessary Dockerfiles, run tests and print the directory. +At that point, you may enter it and use any of the desired Dockerfiles as per usual. + +CAUTION: This process currently relies on Alpine already being available as a specific tagged image. diff --git a/docs/caveats.adoc b/docs/caveats.adoc new file mode 100644 index 0000000..ff74c5c --- /dev/null +++ b/docs/caveats.adoc @@ -0,0 +1,24 @@ += Caveats + +The musl libc may work differently than what you are used to. +Musl's https://wiki.musl-libc.org/functional-differences-from-glibc.html[functional differences from glibc] document does a good job of outlining everything. +Please do go over it. +This document will outline the most common kinds of issues you are likely to find. + +== Incompatible Binaries + +While there are binaries that will run on musl libc without needing to be recompiled, you will likely encounter binaries and applications that rely on specific glibc functionality that will fail to start up. +An example of this would be Oracle's Java implementation, which relies on specific symbols only found in glibc. +You can often use ldd to determine the exact symbol: +[source] +---- +# ldd bin/java + /lib64/ld-linux-x86-64.so.2 (0x7f542ebb5000) + libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7f542ebb5000) + libjli.so => bin/../lib/amd64/jli/libjli.so (0x7f542e9a0000) + libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7f542ebb5000) + libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f542ebb5000) +Error relocating bin/../lib/amd64/jli/libjli.so: __rawmemchr: symbol not found +---- +In this case, upstream would need to remove the dependency on the offending symbol, or offer you the ability to compile the software natively on a musl-based system. +Be sure to check the https://pkgs.alpinelinux.org[Alpine Linux package index] to see if a suitable replacement package already exists. diff --git a/docs/usage.adoc b/docs/usage.adoc new file mode 100644 index 0000000..fc71079 --- /dev/null +++ b/docs/usage.adoc @@ -0,0 +1,45 @@ += Usage + +== Packages +Replacing your current base image with the Docker Alpine Linux image usually requires updating the package names to the corresponding ones in the https://pkgs.alpinelinux.org[Alpine Linux package index]. +We use the `apk` command to manage packages. +It works similarly to `apt` and `yum`. + +For example, installing the `nginx` package would be done by running `apk add --no-cache nginx`. +The `--no-cache` argument prevents `apk` from caching the package index - something that would normally take up precious space, as well as go stale quickly. + +=== Example +This is an example of a complete Dockerfile for `nginx`: +[source, docker] +---- +FROM alpine + +RUN apk --no-cache add nginx + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] +---- + +=== Virtual Packages +Another great `apk` feature is the concept of user-defined virtual packages. +Packages added under a virtual package name can later be removed as one group. +An example use-case would be removing all build dependencies at once, as in this example: +[source, docker] +---- +FROM alpine + +WORKDIR /myapp +COPY . /myapp + +RUN apk add --no-cache python py-pip openssl ca-certificates +RUN apk add --no-cache --virtual build-dependencies python-dev build-base wget \ + && pip install -r requirements.txt \ + && python setup.py install \ + && apk del build-dependencies + +CMD ["myapp", "start"] +---- + +// COMBAK: update docs link +=== Further Details +For further details on `apk` and how it's used, you can look at https://docs.alpinelinux.org/user-handbook/0.1a/Working/apk.html[Alpine's User Documentation] for it.