├── .gitignore ├── versions ├── library-2.6 │ ├── Dockerfile │ └── options ├── library-2.7 │ ├── Dockerfile │ └── options ├── library-3.1 │ ├── Dockerfile │ └── options ├── library-edge │ ├── Dockerfile │ └── options ├── gliderlabs-2.6 │ ├── Dockerfile │ └── options ├── gliderlabs-2.7 │ ├── Dockerfile │ └── options ├── gliderlabs-3.1 │ ├── Dockerfile │ └── options └── gliderlabs-edge │ ├── Dockerfile │ └── options ├── logo.png ├── README-short.txt ├── test ├── test_alpine-2.6.bats ├── test_alpine-2.7.bats ├── test_alpine-3.1.bats ├── test_alpine-edge.bats ├── test_gliderlabs_alpine-2.6.bats ├── test_gliderlabs_alpine-2.7.bats ├── test_gliderlabs_alpine-3.1.bats └── test_gliderlabs_alpine-edge.bats ├── circle.yml ├── LICENSE ├── docs ├── build.md ├── about.md ├── usage.md ├── caveats.md └── index.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /images 2 | /versions/**/rootfs.tar.gz 3 | -------------------------------------------------------------------------------- /versions/library-2.6/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD rootfs.tar.gz / 3 | -------------------------------------------------------------------------------- /versions/library-2.7/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD rootfs.tar.gz / 3 | -------------------------------------------------------------------------------- /versions/library-3.1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD rootfs.tar.gz / 3 | -------------------------------------------------------------------------------- /versions/library-edge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD rootfs.tar.gz / 3 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/docker-alpine/master/logo.png -------------------------------------------------------------------------------- /versions/gliderlabs-2.6/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD rootfs.tar.gz / 3 | -------------------------------------------------------------------------------- /versions/gliderlabs-2.7/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD rootfs.tar.gz / 3 | -------------------------------------------------------------------------------- /versions/gliderlabs-3.1/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD rootfs.tar.gz / 3 | -------------------------------------------------------------------------------- /versions/gliderlabs-edge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | ADD rootfs.tar.gz / 3 | -------------------------------------------------------------------------------- /README-short.txt: -------------------------------------------------------------------------------- 1 | A minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size! 2 | -------------------------------------------------------------------------------- /versions/library-2.6/options: -------------------------------------------------------------------------------- 1 | export RELEASE="v2.6" 2 | export BUILD_OPTIONS="-s -t UTC -r ${RELEASE} -m http://dl-4.alpinelinux.org/alpine" 3 | export TAGS="alpine:2.6" 4 | -------------------------------------------------------------------------------- /versions/library-2.7/options: -------------------------------------------------------------------------------- 1 | export RELEASE="v2.7" 2 | export BUILD_OPTIONS="-s -t UTC -r ${RELEASE} -m http://dl-4.alpinelinux.org/alpine" 3 | export TAGS="alpine:2.7" 4 | -------------------------------------------------------------------------------- /versions/gliderlabs-2.6/options: -------------------------------------------------------------------------------- 1 | export RELEASE="v2.6" 2 | export BUILD_OPTIONS="-s -c -t UTC -r ${RELEASE} -m http://dl-4.alpinelinux.org/alpine" 3 | export TAGS="gliderlabs/alpine:2.6" 4 | -------------------------------------------------------------------------------- /versions/gliderlabs-2.7/options: -------------------------------------------------------------------------------- 1 | export RELEASE="v2.7" 2 | export BUILD_OPTIONS="-s -c -t UTC -r ${RELEASE} -m http://dl-4.alpinelinux.org/alpine" 3 | export TAGS="gliderlabs/alpine:2.7" 4 | -------------------------------------------------------------------------------- /versions/library-edge/options: -------------------------------------------------------------------------------- 1 | export RELEASE="edge" 2 | export MIRROR="http://dl-4.alpinelinux.org/alpine" 3 | export BUILD_OPTIONS="-s -t UTC -r $RELEASE -m $MIRROR" 4 | export TAGS="alpine:edge" 5 | -------------------------------------------------------------------------------- /versions/library-3.1/options: -------------------------------------------------------------------------------- 1 | export RELEASE="v3.1" 2 | export MIRROR="http://dl-4.alpinelinux.org/alpine" 3 | export BUILD_OPTIONS="-s -t UTC -r $RELEASE -m $MIRROR" 4 | export TAGS="alpine:3.1 alpine:latest" 5 | -------------------------------------------------------------------------------- /versions/gliderlabs-edge/options: -------------------------------------------------------------------------------- 1 | export RELEASE="edge" 2 | export MIRROR="http://dl-4.alpinelinux.org/alpine" 3 | export BUILD_OPTIONS="-s -c -t UTC -r $RELEASE -m $MIRROR" 4 | export TAGS="gliderlabs/alpine:edge" 5 | -------------------------------------------------------------------------------- /versions/gliderlabs-3.1/options: -------------------------------------------------------------------------------- 1 | export RELEASE="v3.1" 2 | export MIRROR="http://dl-4.alpinelinux.org/alpine" 3 | export BUILD_OPTIONS="-s -c -t UTC -r $RELEASE -m $MIRROR" 4 | export TAGS="gliderlabs/alpine:3.1 gliderlabs/alpine:latest" 5 | -------------------------------------------------------------------------------- /test/test_alpine-2.6.bats: -------------------------------------------------------------------------------- 1 | setup() { 2 | docker history alpine:2.6 >/dev/null 2>&1 3 | } 4 | 5 | @test "version is correct" { 6 | run docker run alpine:2.6 cat /etc/alpine-release 7 | [ $status -eq 0 ] 8 | [ "${lines[0]}" = "2.6.6" ] 9 | } 10 | 11 | @test "package installs cleanly" { 12 | run docker run alpine:2.6 apk add --update openssl 13 | [ $status -eq 0 ] 14 | } 15 | 16 | @test "timezone" { 17 | run docker run alpine:2.6 date +%Z 18 | [ $status -eq 0 ] 19 | [ "$output" = "UTC" ] 20 | } 21 | 22 | @test "apk-install script should be missing" { 23 | run docker run alpine:2.6 which apk-install 24 | [ $status -eq 1 ] 25 | } 26 | 27 | @test "repository list is correct" { 28 | run docker run alpine:2.6 cat /etc/apk/repositories 29 | [ $status -eq 0 ] 30 | [ "${lines[0]}" = "http://dl-4.alpinelinux.org/alpine/v2.6/main" ] 31 | } 32 | 33 | @test "cache is empty" { 34 | run docker run alpine:2.6 sh -c "ls -1 /var/cache/apk | wc -l" 35 | [ $status -eq 0 ] 36 | [ "$output" = "0" ] 37 | } 38 | -------------------------------------------------------------------------------- /test/test_alpine-2.7.bats: -------------------------------------------------------------------------------- 1 | setup() { 2 | docker history alpine:2.7 >/dev/null 2>&1 3 | } 4 | 5 | @test "version is correct" { 6 | run docker run alpine:2.7 cat /etc/alpine-release 7 | [ $status -eq 0 ] 8 | [ "${lines[0]}" = "2.7.9" ] 9 | } 10 | 11 | @test "package installs cleanly" { 12 | run docker run alpine:2.7 apk add --update openssl 13 | [ $status -eq 0 ] 14 | } 15 | 16 | @test "timezone" { 17 | run docker run alpine:2.7 date +%Z 18 | [ $status -eq 0 ] 19 | [ "$output" = "UTC" ] 20 | } 21 | 22 | @test "apk-install script should be missing" { 23 | run docker run alpine:2.7 which apk-install 24 | [ $status -eq 1 ] 25 | } 26 | 27 | @test "repository list is correct" { 28 | run docker run alpine:2.7 cat /etc/apk/repositories 29 | [ $status -eq 0 ] 30 | [ "${lines[0]}" = "http://dl-4.alpinelinux.org/alpine/v2.7/main" ] 31 | } 32 | 33 | @test "cache is empty" { 34 | run docker run alpine:2.7 sh -c "ls -1 /var/cache/apk | wc -l" 35 | [ $status -eq 0 ] 36 | [ "$output" = "0" ] 37 | } 38 | -------------------------------------------------------------------------------- /test/test_alpine-3.1.bats: -------------------------------------------------------------------------------- 1 | setup() { 2 | docker history "alpine:3.1" >/dev/null 2>&1 3 | } 4 | 5 | @test "version is correct" { 6 | run docker run "alpine:3.1" cat /etc/os-release 7 | [ $status -eq 0 ] 8 | [ "${lines[2]}" = "VERSION_ID=3.1.2" ] 9 | } 10 | 11 | @test "package installs cleanly" { 12 | run docker run "alpine:3.1" apk add --update openssl 13 | [ $status -eq 0 ] 14 | } 15 | 16 | @test "timezone" { 17 | run docker run "alpine:3.1" date +%Z 18 | [ $status -eq 0 ] 19 | [ "$output" = "UTC" ] 20 | } 21 | 22 | @test "apk-install script should be missing" { 23 | run docker run "alpine:3.1" which apk-install 24 | [ $status -eq 1 ] 25 | } 26 | 27 | @test "repository list is correct" { 28 | run docker run "alpine:3.1" cat /etc/apk/repositories 29 | [ $status -eq 0 ] 30 | [ "${lines[0]}" = "http://dl-4.alpinelinux.org/alpine/v3.1/main" ] 31 | } 32 | 33 | @test "cache is empty" { 34 | run docker run "alpine:3.1" sh -c "ls -1 /var/cache/apk | wc -l" 35 | [ $status -eq 0 ] 36 | [ "$output" = "0" ] 37 | } 38 | -------------------------------------------------------------------------------- /test/test_alpine-edge.bats: -------------------------------------------------------------------------------- 1 | setup() { 2 | docker history "alpine:edge" >/dev/null 2>&1 3 | } 4 | 5 | @test "version is correct" { 6 | run docker run "alpine:edge" cat /etc/os-release 7 | [ $status -eq 0 ] 8 | [ "${lines[2]}" = "VERSION_ID=3.2.0_alpha1" ] 9 | } 10 | 11 | @test "package installs cleanly" { 12 | run docker run "alpine:edge" apk add --update openssl 13 | [ $status -eq 0 ] 14 | } 15 | 16 | @test "timezone" { 17 | run docker run "alpine:edge" date +%Z 18 | [ $status -eq 0 ] 19 | [ "$output" = "UTC" ] 20 | } 21 | 22 | @test "apk-install script should be missing" { 23 | run docker run "alpine:edge" which apk-install 24 | [ $status -eq 1 ] 25 | } 26 | 27 | @test "repository list is correct" { 28 | run docker run "alpine:edge" cat /etc/apk/repositories 29 | [ $status -eq 0 ] 30 | [ "${lines[0]}" = "http://dl-4.alpinelinux.org/alpine/edge/main" ] 31 | } 32 | 33 | @test "cache is empty" { 34 | run docker run "alpine:edge" sh -c "ls -1 /var/cache/apk | wc -l" 35 | [ $status -eq 0 ] 36 | [ "$output" = "0" ] 37 | } 38 | -------------------------------------------------------------------------------- /test/test_gliderlabs_alpine-2.6.bats: -------------------------------------------------------------------------------- 1 | setup() { 2 | docker history gliderlabs/alpine:2.6 >/dev/null 2>&1 3 | } 4 | 5 | @test "version is correct" { 6 | run docker run gliderlabs/alpine:2.6 cat /etc/alpine-release 7 | [ $status -eq 0 ] 8 | [ "${lines[0]}" = "2.6.6" ] 9 | } 10 | 11 | @test "package installs cleanly" { 12 | run docker run gliderlabs/alpine:2.6 apk add --update openssl 13 | [ $status -eq 0 ] 14 | } 15 | 16 | @test "timezone" { 17 | run docker run gliderlabs/alpine:2.6 date +%Z 18 | [ $status -eq 0 ] 19 | [ "$output" = "UTC" ] 20 | } 21 | 22 | @test "apk-install script should be available" { 23 | run docker run gliderlabs/alpine:2.6 which apk-install 24 | [ $status -eq 0 ] 25 | } 26 | 27 | @test "repository list is correct" { 28 | run docker run gliderlabs/alpine:2.6 cat /etc/apk/repositories 29 | [ $status -eq 0 ] 30 | [ "${lines[0]}" = "http://dl-4.alpinelinux.org/alpine/v2.6/main" ] 31 | } 32 | 33 | @test "cache is empty" { 34 | run docker run gliderlabs/alpine:2.6 sh -c "ls -1 /var/cache/apk | wc -l" 35 | [ $status -eq 0 ] 36 | [ "$output" = "0" ] 37 | } 38 | -------------------------------------------------------------------------------- /test/test_gliderlabs_alpine-2.7.bats: -------------------------------------------------------------------------------- 1 | setup() { 2 | docker history gliderlabs/alpine:2.7 >/dev/null 2>&1 3 | } 4 | 5 | @test "version is correct" { 6 | run docker run gliderlabs/alpine:2.7 cat /etc/alpine-release 7 | [ $status -eq 0 ] 8 | [ "${lines[0]}" = "2.7.9" ] 9 | } 10 | 11 | @test "package installs cleanly" { 12 | run docker run gliderlabs/alpine:2.7 apk add --update openssl 13 | [ $status -eq 0 ] 14 | } 15 | 16 | @test "timezone" { 17 | run docker run gliderlabs/alpine:2.7 date +%Z 18 | [ $status -eq 0 ] 19 | [ "$output" = "UTC" ] 20 | } 21 | 22 | @test "apk-install script should be available" { 23 | run docker run gliderlabs/alpine:2.7 which apk-install 24 | [ $status -eq 0 ] 25 | } 26 | 27 | @test "repository list is correct" { 28 | run docker run gliderlabs/alpine:2.7 cat /etc/apk/repositories 29 | [ $status -eq 0 ] 30 | [ "${lines[0]}" = "http://dl-4.alpinelinux.org/alpine/v2.7/main" ] 31 | } 32 | 33 | @test "cache is empty" { 34 | run docker run gliderlabs/alpine:2.7 sh -c "ls -1 /var/cache/apk | wc -l" 35 | [ $status -eq 0 ] 36 | [ "$output" = "0" ] 37 | } 38 | -------------------------------------------------------------------------------- /test/test_gliderlabs_alpine-3.1.bats: -------------------------------------------------------------------------------- 1 | setup() { 2 | docker history gliderlabs/alpine:3.1 >/dev/null 2>&1 3 | } 4 | 5 | @test "version is correct" { 6 | run docker run gliderlabs/alpine:3.1 cat /etc/os-release 7 | [ $status -eq 0 ] 8 | [ "${lines[2]}" = "VERSION_ID=3.1.2" ] 9 | } 10 | 11 | @test "package installs cleanly" { 12 | run docker run gliderlabs/alpine:3.1 apk add --update openssl 13 | [ $status -eq 0 ] 14 | } 15 | 16 | @test "timezone" { 17 | run docker run gliderlabs/alpine:3.1 date +%Z 18 | [ $status -eq 0 ] 19 | [ "$output" = "UTC" ] 20 | } 21 | 22 | @test "apk-install script should be available" { 23 | run docker run gliderlabs/alpine:3.1 which apk-install 24 | [ $status -eq 0 ] 25 | } 26 | 27 | @test "repository list is correct" { 28 | run docker run gliderlabs/alpine:3.1 cat /etc/apk/repositories 29 | [ $status -eq 0 ] 30 | [ "${lines[0]}" = "http://dl-4.alpinelinux.org/alpine/v3.1/main" ] 31 | } 32 | 33 | @test "cache is empty" { 34 | run docker run gliderlabs/alpine:3.1 sh -c "ls -1 /var/cache/apk | wc -l" 35 | [ $status -eq 0 ] 36 | [ "$output" = "0" ] 37 | } 38 | -------------------------------------------------------------------------------- /test/test_gliderlabs_alpine-edge.bats: -------------------------------------------------------------------------------- 1 | setup() { 2 | docker history gliderlabs/alpine:edge >/dev/null 2>&1 3 | } 4 | 5 | @test "version is correct" { 6 | run docker run gliderlabs/alpine:edge cat /etc/os-release 7 | [ $status -eq 0 ] 8 | [ "${lines[2]}" = "VERSION_ID=3.2.0_alpha1" ] 9 | } 10 | 11 | @test "package installs cleanly" { 12 | run docker run gliderlabs/alpine:edge apk add --update openssl 13 | [ $status -eq 0 ] 14 | } 15 | 16 | @test "timezone" { 17 | run docker run gliderlabs/alpine:edge date +%Z 18 | [ $status -eq 0 ] 19 | [ "$output" = "UTC" ] 20 | } 21 | 22 | @test "apk-install script should be available" { 23 | run docker run gliderlabs/alpine:edge which apk-install 24 | [ $status -eq 0 ] 25 | } 26 | 27 | @test "repository list is correct" { 28 | run docker run gliderlabs/alpine:edge cat /etc/apk/repositories 29 | [ $status -eq 0 ] 30 | [ "${lines[0]}" = "http://dl-4.alpinelinux.org/alpine/edge/main" ] 31 | } 32 | 33 | @test "cache is empty" { 34 | run docker run gliderlabs/alpine:edge sh -c "ls -1 /var/cache/apk | wc -l" 35 | [ $status -eq 0 ] 36 | [ "$output" = "0" ] 37 | } 38 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | general: 2 | artifacts: 3 | - "images" 4 | branches: 5 | ignore: 6 | - /rootfs-.*/ 7 | 8 | machine: 9 | services: 10 | - docker 11 | 12 | dependencies: 13 | cache_directories: 14 | - "~/docker" 15 | - "~/deps" 16 | pre: 17 | - if [[ ! -e ~/deps/bats_v0.4.0.tar.gz ]]; then mkdir -p ~/deps; curl -sSL -o ~/deps/bats_v0.4.0.tar.gz https://github.com/sstephenson/bats/archive/v0.4.0.tar.gz; fi 18 | - tar -xf ~/deps/bats_v0.4.0.tar.gz 19 | - sudo bats-0.4.0/install.sh /usr/local 20 | override: 21 | - docker info 22 | - if [[ -e ~/docker/builder.tar ]]; then docker load --input ~/docker/builder.tar; fi 23 | - ./build: 24 | parallel: true 25 | files: 26 | - versions/**/options 27 | - mkdir -p ~/docker; docker save alpine-builder > ~/docker/builder.tar 28 | - docker images 29 | 30 | test: 31 | override: 32 | - ./build test: 33 | parallel: true 34 | files: 35 | - versions/**/options 36 | 37 | deployment: 38 | hub: 39 | branch: release 40 | commands: 41 | - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASSWORD: 42 | parallel: true 43 | - docker push gliderlabs/alpine: 44 | parallel: true 45 | - ./build commit: 46 | parallel: true 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Glider Labs, LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /docs/build.md: -------------------------------------------------------------------------------- 1 | # Build 2 | 3 | [![CircleCI](https://img.shields.io/circleci/project/gliderlabs/docker-alpine/release.svg)](https://circleci.com/gh/gliderlabs/docker-alpine) 4 | 5 | A convenience `build` script is included that builds the image and runs basic tests against the resulting image tags. The script is used in the continuous integration process (check out the CircleCI badge badge link above). But you can run this script locally to build your own images. Be sure to check out the environment variables that can be tweaked at the top of the `build` script file. 6 | 7 | ## Image 8 | 9 | The image is built using a builder Docker container based on the `debian` image. This builder image lives in the `builder` sub-directory of the project and uses a `mkimage-alpine.sh` script to generate a Alpine Linux `rootfs.tar.gz` file. This file then gets copied to the root of the project so we can build the main Alpine Linux image by just using the `ADD` command to automatically untar the components to the resulting image. 10 | 11 | The build script takes a glob of `tags` files as an argument. Each of these files lives in a folder that describes the version of Alpine Linux to build in the parent directory name and each line of the file are the tags that will be applied to the resulting image. By default, we use the included glob of `versions/**/tags`. 12 | 13 | ## Test 14 | 15 | The test for images is very simple at the moment. It just attempts to install the `openssl` package and verify we exit cleanly. 16 | 17 | Use the `test` sub-command of the `build` utility to run tests on currently build images (`build test`). 18 | -------------------------------------------------------------------------------- /docs/about.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | [Alpine Linux][http://alpinelinux.org/] is a lightweight Linux distribution based on [musl libc][musl] and [BusyBox][busybox]. The base is extremely small, builds as a Docker image in a matter of minutes, and has a full-featured package index. 4 | 5 | ## musl libc 6 | 7 | musl provides consistent quality and implementation behavior from tiny embedded systems to full-fledged servers. 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. 8 | 9 | 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 can really 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. 10 | 11 | ## BusyBox 12 | 13 | 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 options than their full-featured GNU cousins; however, the options that are included provide the expected functionality and behave very much like their GNU counterparts. BusyBox provides a fairly complete environment for any small or embedded system. 14 | 15 | 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. 16 | 17 | ## Match made in heaven 18 | 19 | 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. 20 | 21 | [musl]: http://www.musl-libc.org/ 22 | [busybox]: http://www.busybox.net/ 23 | -------------------------------------------------------------------------------- /docs/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | ## Packages 4 | 5 | Replacing your current base image with the Docker Alpine Linux image usually requires updating the package names to the corresponding ones in the [Alpine Linux package index][packageindex]. We use the `apk` command to manage packages. It works similar to `apt` or `yum`. 6 | 7 | An example installing the `nginx` package would be `apk add --update nginx`. The `--update` flag fetches the current package index before adding the package. We don't ship the image with a package index (since that can go stale fairly quickly). 8 | 9 | ## Example 10 | 11 | Here is a full example `Dockerfile` that installs the Python runtime and some build dependencies: 12 | 13 | ``` 14 | FROM gliderlabs/alpine:3.1 15 | 16 | RUN apk add --update \ 17 | python \ 18 | python-dev \ 19 | py-pip \ 20 | build-base \ 21 | && pip install virtualenv \ 22 | && rm -rf /var/cache/apk/* 23 | 24 | WORKDIR /app 25 | 26 | ONBUILD COPY . /app 27 | ONBUILD RUN virtualenv /env && /env/bin/pip install -r /app/requirements.txt 28 | 29 | EXPOSE 8080 30 | CMD ["/env/bin/python", "main.py"] 31 | ``` 32 | 33 | Notice `rm -rf /var/cache/apk/*` at the end of the `apk add` command. This is good practice to cleanup when you're done using `apk add` to use as little disk space as possible. After all, that's why you're using Alpine here, right? 34 | 35 | ## Virtual Packages 36 | 37 | A great `apk add` feature for cleanup is the concept of virtual packages using the `--virtual` or `-t` switch. Packages added under this virtual name can then be removed as one group. An example use of this would be removing a group of build dependencies all at once: 38 | 39 | ``` 40 | FROM gliderlabs/alpine:3.1 41 | 42 | WORKDIR /myapp 43 | COPY . /myapp 44 | 45 | RUN apk --update add python py-pip openssl ca-certificates 46 | RUN apk --update add --virtual build-dependencies python-dev build-base wget \ 47 | && pip install -r requirements.txt \ 48 | && python setup.py install \ 49 | && apk del build-dependencies 50 | 51 | CMD ["myapp", "start"] 52 | ``` 53 | 54 | ## Additional Information 55 | 56 | Check out the [Alpine Linux package management documentation][apk] for more information and usage of `apk`. 57 | 58 | [apk]: http://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management#Update_the_Package_list 59 | [packageindex]: http://forum.alpinelinux.org/packages 60 | -------------------------------------------------------------------------------- /docs/caveats.md: -------------------------------------------------------------------------------- 1 | # Caveats 2 | 3 | The musl libc implementation may work a little different than you are used to. The [musl libc differences from glibc document](http://wiki.musl-libc.org/wiki/Functional_differences_from_glibc#Name_Resolver_.2F_DNS) does a really good job of outlining everything. Please take a glance at it. Here we'll talk about some of the more common things you might encounter. 4 | 5 | ## DNS 6 | 7 | One common issue you may find is with DNS. musl libc does not use `domain` or `search` directives in the `/etc/resolv.conf` file. For example, if you started your Docker daemon with `--dns-search=service.consul`, and then tried to resolve `consul` from within an Alpine Linux container, it would fail as the name `consul.service.consul` would not be tried. You will need to work around this by using fully qualified names. 8 | 9 | Another difference is parallel querying of name servers. This can be problematic if your first name server has a different DNS view (such as service discovery through DNS). For example, if you started your Docker daemon with `--dns=172.17.42.1 --dns=10.0.2.15` where `172.17.42.1` is a local DNS server to resolve name for service discovery and `10.0.2.15` is for external DNS resolving, you wouldn't be able to guarantee that `172.17.42.1` will always be queried first. There will be sporadic failures. 10 | 11 | In both of these cases, it can help to run a local caching DNS server such as dnsmasq, that can be used for both caching and search path routing. Running dnsmasq with `--server /consul/10.0.0.1` would forward queries for the `.consul` to 10.0.0.1. 12 | 13 | ## Incompatible Binaries 14 | 15 | 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 Java which relies on specific symbols only found in glibc. You can often use `ldd` to determine the exact symbol: 16 | 17 | ```console 18 | # ldd bin/java 19 | /lib64/ld-linux-x86-64.so.2 (0x7f542ebb5000) 20 | libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7f542ebb5000) 21 | libjli.so => bin/../lib/amd64/jli/libjli.so (0x7f542e9a0000) 22 | libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7f542ebb5000) 23 | libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f542ebb5000) 24 | Error relocating bin/../lib/amd64/jli/libjli.so: __rawmemchr: symbol not found 25 | ``` 26 | 27 | In this case, the upstream would need to remove the support for this offending symbol or have the ability to compile the software natively on musl libc. Be sure to check the [Alpine Linux package index](http://forum.alpinelinux.org/packages) to see if a suitable replacement package already exists. 28 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Alpine Linux Docker Image 2 | 3 | [![CircleCI](https://img.shields.io/circleci/project/gliderlabs/docker-alpine/release.svg)](https://circleci.com/gh/gliderlabs/docker-alpine) [![Docker Hub](https://img.shields.io/badge/docker-ready-blue.svg)](https://registry.hub.docker.com/u/gliderlabs/alpine/) [![IRC Channel](https://img.shields.io/badge/irc-%23gliderlabs-blue.svg)][irc] 4 | 5 | Welcome to the documentation for the Alpine Linux Docker Image. Here we explain a bit about the motivations behind this image, how you typically use it, the build process, and how to make great minimalist containers! 6 | 7 | ## About 8 | 9 | The heart of this image is [Alpine Linux][alpine]. The image is only 5 MB and has access to a package repository that is much more complete than other minimal base images. Learn more [about this image][about], musl libc, BusyBox, and why the Docker Alpine Linux image makes a great base for your Docker projects. 10 | 11 | ## Motivations 12 | 13 | Docker images today are big. Usually much larger than they need to be. There are a lot of ways to make them smaller. But you need to start with a small base. There are great size savings to be had when compared to base images such as `ubuntu`, `centos`, and `debian`. 14 | 15 | ## Usage 16 | 17 | You use the `apk` command to manage packages. We don't ship the image with a package index (since that can go stale fairly quickly), so you need to add the `--update` flag to `apk` when installing. An example installing the `nginx` package would be `apk add --update nginx`. Check out [the usage page][usage] for more advanced usage and `Dockerfile` examples. 18 | 19 | ## Caveats 20 | 21 | The musl libc implementation may work a little different than you are used to. One example of this is with DNS. musl libc does not use `domain` or `search` in the `/etc/resolv.conf` file. It also queries name servers in parallel which can be problematic if your first name server has a different DNS view (such as service discovery through DNS). We have [a page dedicated to the caveats][caveats] you should be aware of. 22 | 23 | ## Build 24 | 25 | This image is built and tested in a continuous integration environment using the `build` script. We then push the resulting images directly to Docker Hub. Check out [the page on building and testing][build] the images for more information. 26 | 27 | ## Support 28 | 29 | We make reasonable efforts to support our work and are always happy to chat. Feel free to join us in [#gliderlabs on Freenode][irc] or [submit an issue][issues] to the GitHub repository. 30 | 31 | ## Contributing 32 | 33 | We welcome contributions to the image build process, version bumps, and other optimizations. The image gets built and pushed from the `release` branch automatically. Once a pull request is merged, a build will be kicked off, and resulting image pushed to Docker Hub in a matter of minutes! 34 | 35 | [about]: /docker-alpine/about 36 | [usage]: /docker-alpine/usage 37 | [build]: /docker-alpine/build 38 | [caveats]: /docker-alpine/caveats 39 | [irc]: https://kiwiirc.com/client/irc.freenode.net/#gliderlabs 40 | [issues]: https://github.com/gliderlabs/docker-alpine/issues 41 | [alpine]: http://alpinelinux.org/ 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-alpine 2 | 3 | [![CircleCI](https://img.shields.io/circleci/project/gliderlabs/docker-alpine/release.svg)](https://circleci.com/gh/gliderlabs/docker-alpine) [![Docker Hub](https://img.shields.io/badge/docker-ready-blue.svg)](https://registry.hub.docker.com/u/gliderlabs/alpine/) [![IRC Channel](https://img.shields.io/badge/irc-%23gliderlabs-blue.svg)][irc] 4 | 5 | A super small Docker image based on [Alpine Linux][alpine]. The image is only 5 MB and has access to a package repository that is much more complete than other BusyBox based images. 6 | 7 | ## Why? 8 | 9 | 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 populous still jumps to the `ubuntu` base image for most projects. The size savings over `ubuntu` and other bases are huge: 10 | 11 | ``` 12 | REPOSITORY TAG IMAGE ID VIRTUAL SIZE 13 | gliderlabs/alpine latest 157314031a17 5.03 MB 14 | debian latest 4d6ce913b130 84.98 MB 15 | ubuntu latest b39b81afc8ca 188.3 MB 16 | centos latest 8efe422e6104 210 MB 17 | ``` 18 | 19 | There are images such as `progrium/busybox` which get us very 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 complete and update to date [package index][alpine-packages]: 20 | 21 | ```console 22 | $ docker run progrium/busybox opkg-install nodejs 23 | Unknown package 'nodejs'. 24 | Collected errors: 25 | * opkg_install_cmd: Cannot install package nodejs. 26 | 27 | $ docker run gliderlabs/alpine apk --update add nodejs 28 | fetch http://dl-4.alpinelinux.org/alpine/v3.1/main/x86_64/APKINDEX.tar.gz 29 | (1/5) Installing c-ares (1.10.0-r1) 30 | (2/5) Installing libgcc (4.8.3-r0) 31 | (3/5) Installing libstdc++ (4.8.3-r0) 32 | (4/5) Installing libuv (0.10.29-r0) 33 | (5/5) Installing nodejs (0.10.33-r0) 34 | Executing busybox-1.22.1-r14.trigger 35 | OK: 21 MiB in 20 packages 36 | ``` 37 | 38 | This makes Alpine Linux a great image base for utilities and even production applications. [Read more about Alpine Linux here][alpine-about] and you can see how their mantra fits in right at home with Docker images. 39 | 40 | ## Usage 41 | 42 | Stop doing this: 43 | 44 | ``` 45 | FROM ubuntu-debootstrap:14.04 46 | RUN apt-get update -q \ 47 | && DEBIAN_FRONTEND=noninteractive apt-get install -qy mysql-client \ 48 | && apt-get clean \ 49 | && rm -rf /var/lib/apt 50 | ENTRYPOINT ["mysql"] 51 | ``` 52 | This took 19 seconds to build and yields a 164 MB image. Eww. Start doing this: 53 | 54 | ``` 55 | FROM gliderlabs/alpine:3.1 56 | RUN apk --update add mysql-client 57 | ENTRYPOINT ["mysql"] 58 | ``` 59 | 60 | Only 3 seconds to build and results in a 16 MB image! Hooray! 61 | 62 | ## Documentation 63 | 64 | This image is well documented. [Check out the documentation at Viewdocs][docs] and the `docs` directory in this repository. 65 | 66 | ## Support 67 | 68 | We make reasonable efforts to support our work and are always happy to chat. Feel free to join us in [#gliderlabs on Freenode][irc] or [submit an issue][issues] to this GitHub repository. 69 | 70 | ## Inspiration 71 | 72 | The motivation for this project and modifications to `mkimage.sh` are highly inspired by Eivind Uggedal (uggedal) and Luis Lavena (luislavena). They have made great strides in getting Alpine Linux running as a Docker container. Check out their [mini-container/base][mini-base] image as well. 73 | 74 | ## License 75 | 76 | The code in this repository, unless otherwise noted, is BSD licensed. See the `LICENSE` file in this repository. 77 | 78 | [mini-base]: https://github.com/mini-containers/base 79 | [alpine-packages]: http://forum.alpinelinux.org/packages 80 | [alpine-about]: https://www.alpinelinux.org/about/ 81 | [docs]: http://gliderlabs.viewdocs.io/docker-alpine 82 | [irc]: https://kiwiirc.com/client/irc.freenode.net/#gliderlabs 83 | [issues]: https://github.com/gliderlabs/docker-alpine/issues 84 | [alpine]: http://alpinelinux.org/ 85 | --------------------------------------------------------------------------------