Skip to content

Instantly share code, notes, and snippets.

@proppy
Last active December 6, 2022 09:32
Show Gist options
  • Save proppy/7414e15b97ae221305a1 to your computer and use it in GitHub Desktop.
Save proppy/7414e15b97ae221305a1 to your computer and use it in GitHub Desktop.
apk2layer

apk2layer

apk2layer flattens an alpine linux package(s) and its dependencies into a standalone tarball.

Usage

apk2layer [-mirror] PKGNAME... > layer.tar

Examples

Busybox

alpine 🍙  go run apk2layer.go busybox | docker import - alpine-busybox ; docker images alpine-busybox
2015/06/26 02:49:02 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz: "200 OK"
2015/06/26 02:49:02 busybox=1.23.2-r0
2015/06/26 02:49:02 musl=1.1.9-r2
2015/06/26 02:49:02 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/busybox-1.23.2-r0.apk: "200 OK"
2015/06/26 02:49:02 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/musl-1.1.9-r2.apk: "200 OK"
f7ef1b9406af6bbe2f316fa1a8e4c313b6977f3b4f669ea827da3268b9b7ad90
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
alpine-busybox      latest              f7ef1b9406af        1 seconds ago       1.371 MB
alpine 🍙  docker run -ti alpine-busybox /bin/busybox date
Fri Jun 26 09:49:35 GMT 2015

Nginx

alpine 🍡  go run apk2layer.go nginx | docker import - alpine-nginx ; docker images alpine-nginx
2015/06/26 02:46:05 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz: "200 OK"
2015/06/26 02:46:05 nginx=1.8.0-r1
2015/06/26 02:46:05 busybox=1.23.2-r0
2015/06/26 02:46:05 musl=1.1.9-r2
2015/06/26 02:46:05 libcrypto1.0=1.0.2c-r0
2015/06/26 02:46:05 zlib=1.2.8-r1
2015/06/26 02:46:05 pcre=8.37-r0
2015/06/26 02:46:05 libssl1.0=1.0.2c-r0
2015/06/26 02:46:05 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libssl1.0-1.0.2c-r0.apk: "200 OK"
2015/06/26 02:46:06 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/nginx-1.8.0-r1.apk: "200 OK"
2015/06/26 02:46:06 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/busybox-1.23.2-r0.apk: "200 OK"
2015/06/26 02:46:06 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/musl-1.1.9-r2.apk: "200 OK"
2015/06/26 02:46:06 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libcrypto1.0-1.0.2c-r0.apk: "200 OK"
2015/06/26 02:46:07 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/zlib-1.2.8-r1.apk: "200 OK"
2015/06/26 02:46:07 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/pcre-8.37-r0.apk: "200 OK"
a33046d95be09345118f51163ade1c5bc060281c355fbc977538c7d3a8b76bdc
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
alpine-nginx        latest              a33046d95be0        1 seconds ago       5.807 MB
alpine 🍡  docker run -ti alpine-nginx /usr/sbin/nginx -v
nginx version: nginx/1.8.0

Node

alpine 🍡  go run apk2layer.go nodejs | docker import - alpine-nodejs ; docker images alpine-nodejs
2015/06/26 02:36:09 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz: "200 OK"
2015/06/26 02:36:10 libssl1.0=1.0.2c-r0
2015/06/26 02:36:10 libstdc++=4.9.2-r5
2015/06/26 02:36:10 libuv=1.5.0-r0
2015/06/26 02:36:10 nodejs=0.12.2-r0
2015/06/26 02:36:10 musl=1.1.9-r2
2015/06/26 02:36:10 libcrypto1.0=1.0.2c-r0
2015/06/26 02:36:10 zlib=1.2.8-r1
2015/06/26 02:36:10 libgcc=4.9.2-r5
2015/06/26 02:36:10 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libcrypto1.0-1.0.2c-r0.apk: "200 OK"
2015/06/26 02:36:10 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/zlib-1.2.8-r1.apk: "200 OK"
2015/06/26 02:36:10 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libgcc-4.9.2-r5.apk: "200 OK"
2015/06/26 02:36:10 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libssl1.0-1.0.2c-r0.apk: "200 OK"
2015/06/26 02:36:10 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libstdc++-4.9.2-r5.apk: "200 OK"
2015/06/26 02:36:11 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libuv-1.5.0-r0.apk: "200 OK"
2015/06/26 02:36:11 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/nodejs-0.12.2-r0.apk: "200 OK"
2015/06/26 02:36:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/musl-1.1.9-r2.apk: "200 OK"
702bab80314d6f3d82c8f685993e31630e871e1b946b0e99780d6c424006abcc
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
alpine-nodejs       latest              702bab80314d        3 seconds ago       20.01 MB
alpine 🍊  docker run -ti alpine-nodejs /usr/bin/node
> console.log('will it crash?')
will it crash?
undefined

Python

alpine 🍙  go run apk2layer.go python | docker import - alpine-python ; docker images alpine-python
2015/06/26 02:34:24 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz: "200 OK"
2015/06/26 02:34:24 expat=2.1.0-r1
2015/06/26 02:34:24 ncurses-libs=5.9-r3
2015/06/26 02:34:24 ncurses-terminfo-base=5.9-r3
2015/06/26 02:34:24 sqlite-libs=3.8.10.2-r0
2015/06/26 02:34:24 libbz2=1.0.6-r3
2015/06/26 02:34:24 musl=1.1.9-r2
2015/06/26 02:34:24 libcrypto1.0=1.0.2c-r0
2015/06/26 02:34:24 zlib=1.2.8-r1
2015/06/26 02:34:24 libssl1.0=1.0.2c-r0
2015/06/26 02:34:24 python=2.7.9-r4
2015/06/26 02:34:24 libffi=3.2.1-r0
2015/06/26 02:34:24 gdbm=1.11-r0
2015/06/26 02:34:24 readline=6.3.008-r0
2015/06/26 02:34:24 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libffi-3.2.1-r0.apk: "200 OK"
2015/06/26 02:34:24 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/gdbm-1.11-r0.apk: "200 OK"
2015/06/26 02:34:24 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/readline-6.3.008-r0.apk: "200 OK"
2015/06/26 02:34:25 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libssl1.0-1.0.2c-r0.apk: "200 OK"
2015/06/26 02:34:25 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/python-2.7.9-r4.apk: "200 OK"
2015/06/26 02:34:29 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/musl-1.1.9-r2.apk: "200 OK"
2015/06/26 02:34:30 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libcrypto1.0-1.0.2c-r0.apk: "200 OK"
2015/06/26 02:34:30 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/zlib-1.2.8-r1.apk: "200 OK"
2015/06/26 02:34:30 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/expat-2.1.0-r1.apk: "200 OK"
2015/06/26 02:34:30 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/ncurses-libs-5.9-r3.apk: "200 OK"
2015/06/26 02:34:30 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/ncurses-terminfo-base-5.9-r3.apk: "200 OK"
2015/06/26 02:34:30 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/sqlite-libs-3.8.10.2-r0.apk: "200 OK"
2015/06/26 02:34:31 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libbz2-1.0.6-r3.apk: "200 OK"
3473123e7795aed7a95381242d4de93e495ff06efd561660c83ac13defa29254
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
alpine-python       latest              3473123e7795        7 seconds ago       39.23 MB
alpine 🍡  docker run -ti alpine-python /usr/bin/python
Python 2.7.9 (default, Apr 24 2015, 14:48:46) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.

Golang

alpine 🍙  go run apk2layer.go go | docker import - alpine-go ; docker images alpine-go
2015/06/26 02:42:01 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz: "200 OK"
2015/06/26 02:42:02 go=1.4.2-r0
2015/06/26 02:42:02 musl=1.1.9-r2
2015/06/26 02:42:02 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/go-1.4.2-r0.apk: "200 OK"
2015/06/26 02:42:15 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/musl-1.1.9-r2.apk: "200 OK"
c3aecfcc075f4efbcebee698f6311126b6a7f0e92e630e1df9d4e28f292f6f43
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
alpine-go           latest              c3aecfcc075f        13 seconds ago      120.9 MB
alpine 🍡  docker run -ti alpine-go /usr/bin/go version
go version go1.4.2 linux/amd64

Java

alpine 🍙  go run apk2layer.go openjdk7-jre | docker import - alpine-java ; docker images alpine-java
2015/06/26 02:37:43 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz: "200 OK"
2015/06/26 02:37:43 gtk+2.0=2.24.25-r0
2015/06/26 02:37:43 gdk-pixbuf=2.30.7-r0
2015/06/26 02:37:43 giflib=5.1.1-r0
2015/06/26 02:37:43 openjdk7-jre-base=7.79.2.5.5-r0
2015/06/26 02:37:43 openjdk7-jre-lib=7.79.2.5.5-r0
2015/06/26 02:37:43 busybox=1.23.2-r0
2015/06/26 02:37:43 gnutls=3.4.1-r0
2015/06/26 02:37:43 tiff=4.0.3-r3
2015/06/26 02:37:43 atk=2.16.0-r0
2015/06/26 02:37:43 libverto=0.2.5-r0
2015/06/26 02:37:43 glib=2.44.0-r1
2015/06/26 02:37:43 libffi=3.2.1-r0
2015/06/26 02:37:43 freetype=2.5.5-r0
2015/06/26 02:37:43 libpng=1.6.16-r0
2015/06/26 02:37:43 libcrypto1.0=1.0.2c-r0
2015/06/26 02:37:43 java-common=0.1-r0
2015/06/26 02:37:43 zlib=1.2.8-r1
2015/06/26 02:37:43 p11-kit=0.23.1-r0
2015/06/26 02:37:43 libxcursor=1.1.14-r1
2015/06/26 02:37:43 libssl1.0=1.0.2c-r0
2015/06/26 02:37:43 libxcb=1.11-r0
2015/06/26 02:37:43 libxi=1.7.4-r0
2015/06/26 02:37:43 libxft=2.3.2-r0
2015/06/26 02:37:43 openjdk7-jre=7.79.2.5.5-r0
2015/06/26 02:37:43 libxdmcp=1.1.2-r0
2015/06/26 02:37:43 cairo=1.14.2-r0
2015/06/26 02:37:43 cups-libs=2.0.3-r0
2015/06/26 02:37:43 musl=1.1.9-r2
2015/06/26 02:37:43 hicolor-icon-theme=0.15-r0
2015/06/26 02:37:43 krb5-libs=1.13.1-r1
2015/06/26 02:37:43 libcom_err=1.42.13-r0
2015/06/26 02:37:43 libxext=1.3.3-r0
2015/06/26 02:37:43 nettle=3.1.1-r0
2015/06/26 02:37:43 shared-mime-info=1.4-r0
2015/06/26 02:37:43 libxml2=2.9.2-r0
2015/06/26 02:37:43 gtk-update-icon-cache=2.24.25-r0
2015/06/26 02:37:43 graphite2=1.2.4-r1
2015/06/26 02:37:43 libx11=1.6.3-r0
2015/06/26 02:37:43 libstdc++=4.9.2-r5
2015/06/26 02:37:43 libxcomposite=0.4.4-r0
2015/06/26 02:37:43 libxdamage=1.1.4-r0
2015/06/26 02:37:43 pango=1.36.8-r0
2015/06/26 02:37:43 alsa-lib=1.0.29-r0
2015/06/26 02:37:43 fontconfig=2.11.1-r1
2015/06/26 02:37:43 libtasn1=4.5-r0
2015/06/26 02:37:43 keyutils-libs=1.5.9-r1
2015/06/26 02:37:43 lcms2=2.7-r0
2015/06/26 02:37:43 krb5-conf=1.0-r0
2015/06/26 02:37:43 libintl=0.19.4-r1
2015/06/26 02:37:43 expat=2.1.0-r1
2015/06/26 02:37:43 pixman=0.32.6-r1
2015/06/26 02:37:43 dbus-libs=1.8.16-r1
2015/06/26 02:37:43 libxfixes=5.0.1-r0
2015/06/26 02:37:43 libxrender=0.9.9-r0
2015/06/26 02:37:43 libgcc=4.9.2-r5
2015/06/26 02:37:43 libxrandr=1.4.2-r0
2015/06/26 02:37:43 harfbuzz=0.9.40-r1
2015/06/26 02:37:43 libxau=1.0.8-r0
2015/06/26 02:37:43 avahi-libs=0.6.31-r7
2015/06/26 02:37:43 gmp=6.0.0a-r0
2015/06/26 02:37:43 libjpeg-turbo=1.4.0-r0
2015/06/26 02:37:43 libxtst=1.2.2-r0
2015/06/26 02:37:43 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/krb5-conf-1.0-r0.apk: "200 OK"
2015/06/26 02:37:43 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libintl-0.19.4-r1.apk: "200 OK"
2015/06/26 02:37:44 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/expat-2.1.0-r1.apk: "200 OK"
2015/06/26 02:37:44 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/pixman-0.32.6-r1.apk: "200 OK"
2015/06/26 02:37:44 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/dbus-libs-1.8.16-r1.apk: "200 OK"
2015/06/26 02:37:44 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxfixes-5.0.1-r0.apk: "200 OK"
2015/06/26 02:37:44 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxrender-0.9.9-r0.apk: "200 OK"
2015/06/26 02:37:44 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libgcc-4.9.2-r5.apk: "200 OK"
2015/06/26 02:37:44 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxrandr-1.4.2-r0.apk: "200 OK"
2015/06/26 02:37:44 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/harfbuzz-0.9.40-r1.apk: "200 OK"
2015/06/26 02:37:44 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxau-1.0.8-r0.apk: "200 OK"
2015/06/26 02:37:45 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/avahi-libs-0.6.31-r7.apk: "200 OK"
2015/06/26 02:37:45 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/gmp-6.0.0a-r0.apk: "200 OK"
2015/06/26 02:37:45 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libjpeg-turbo-1.4.0-r0.apk: "200 OK"
2015/06/26 02:37:45 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxtst-1.2.2-r0.apk: "200 OK"
2015/06/26 02:37:45 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/gtk+2.0-2.24.25-r0.apk: "200 OK"
2015/06/26 02:37:46 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/gdk-pixbuf-2.30.7-r0.apk: "200 OK"
2015/06/26 02:37:46 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/giflib-5.1.1-r0.apk: "200 OK"
2015/06/26 02:37:47 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/openjdk7-jre-base-7.79.2.5.5-r0.apk: "200 OK"
2015/06/26 02:37:52 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/openjdk7-jre-lib-7.79.2.5.5-r0.apk: "200 OK"
2015/06/26 02:38:09 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/busybox-1.23.2-r0.apk: "200 OK"
2015/06/26 02:38:09 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/gnutls-3.4.1-r0.apk: "200 OK"
2015/06/26 02:38:10 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/tiff-4.0.3-r3.apk: "200 OK"
2015/06/26 02:38:10 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/atk-2.16.0-r0.apk: "200 OK"
2015/06/26 02:38:10 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libverto-0.2.5-r0.apk: "200 OK"
2015/06/26 02:38:10 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/glib-2.44.0-r1.apk: "200 OK"
2015/06/26 02:38:11 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libffi-3.2.1-r0.apk: "200 OK"
2015/06/26 02:38:11 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/freetype-2.5.5-r0.apk: "200 OK"
2015/06/26 02:38:11 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libpng-1.6.16-r0.apk: "200 OK"
2015/06/26 02:38:11 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libcrypto1.0-1.0.2c-r0.apk: "200 OK"
2015/06/26 02:38:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/java-common-0.1-r0.apk: "200 OK"
2015/06/26 02:38:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/zlib-1.2.8-r1.apk: "200 OK"
2015/06/26 02:38:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/p11-kit-0.23.1-r0.apk: "200 OK"
2015/06/26 02:38:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxcursor-1.1.14-r1.apk: "200 OK"
2015/06/26 02:38:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libssl1.0-1.0.2c-r0.apk: "200 OK"
2015/06/26 02:38:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxcb-1.11-r0.apk: "200 OK"
2015/06/26 02:38:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxi-1.7.4-r0.apk: "200 OK"
2015/06/26 02:38:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxft-2.3.2-r0.apk: "200 OK"
2015/06/26 02:38:12 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/openjdk7-jre-7.79.2.5.5-r0.apk: "200 OK"
2015/06/26 02:38:13 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxdmcp-1.1.2-r0.apk: "200 OK"
2015/06/26 02:38:13 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/cairo-1.14.2-r0.apk: "200 OK"
2015/06/26 02:38:13 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/cups-libs-2.0.3-r0.apk: "200 OK"
2015/06/26 02:38:13 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/musl-1.1.9-r2.apk: "200 OK"
2015/06/26 02:38:13 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/hicolor-icon-theme-0.15-r0.apk: "200 OK"
2015/06/26 02:38:13 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/krb5-libs-1.13.1-r1.apk: "200 OK"
2015/06/26 02:38:14 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libcom_err-1.42.13-r0.apk: "200 OK"
2015/06/26 02:38:14 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/graphite2-1.2.4-r1.apk: "200 OK"
2015/06/26 02:38:14 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxext-1.3.3-r0.apk: "200 OK"
2015/06/26 02:38:14 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/nettle-3.1.1-r0.apk: "200 OK"
2015/06/26 02:38:14 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/shared-mime-info-1.4-r0.apk: "200 OK"
2015/06/26 02:38:15 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxml2-2.9.2-r0.apk: "200 OK"
2015/06/26 02:38:15 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/gtk-update-icon-cache-2.24.25-r0.apk: "200 OK"
2015/06/26 02:38:15 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libx11-1.6.3-r0.apk: "200 OK"
2015/06/26 02:38:16 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libstdc++-4.9.2-r5.apk: "200 OK"
2015/06/26 02:38:16 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxcomposite-0.4.4-r0.apk: "200 OK"
2015/06/26 02:38:16 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libxdamage-1.1.4-r0.apk: "200 OK"
2015/06/26 02:38:16 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/pango-1.36.8-r0.apk: "200 OK"
2015/06/26 02:38:16 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/alsa-lib-1.0.29-r0.apk: "200 OK"
2015/06/26 02:38:16 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/fontconfig-2.11.1-r1.apk: "200 OK"
2015/06/26 02:38:17 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/libtasn1-4.5-r0.apk: "200 OK"
2015/06/26 02:38:17 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/keyutils-libs-1.5.9-r1.apk: "200 OK"
2015/06/26 02:38:17 GET http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64/lcms2-2.7-r0.apk: "200 OK"
e0ef93968e19bafbb5f7c4098c0449559d36c000b29835749e82a05d268c5d60
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
alpine-java         latest              e0ef93968e19        34 seconds ago      116.5 MB
alpine 🍡  docker run -ti alpine-java /usr/lib/jvm/java-1.7-openjdk/jre/bin/java -version
java version "1.7.0_79"
OpenJDK Runtime Environment (IcedTea 2.5.5) (Alpine 7.79.2.5.5-r0)
OpenJDK 64-Bit Server VM (build 24.79-b02, mixed mode)
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// apk2layer flattens alpine linux package(s) into a standalone tarball.
package main
import (
"archive/tar"
"bufio"
"compress/gzip"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"strings"
)
var mirror = flag.String("mirror", "http://dl-3.alpinelinux.org/alpine/latest-stable/main/x86_64", "alpine mirror url prefix")
func init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\ncat APKINDEX.gz | apkindex [flags] PKGNAME...\n", os.Args[0])
flag.PrintDefaults()
}
}
var (
versions = map[string]string{}
depends = map[string][]string{}
rprovides = map[string]string{}
)
func main() {
flag.Parse()
if flag.NArg() == 0 {
flag.Usage()
os.Exit(1)
}
m := strings.TrimLeft(*mirror, "/")
url := fmt.Sprintf("%s/APKINDEX.tar.gz", m)
r, err := http.Get(url)
if err != nil {
log.Fatalf("error making GET %s: %v", url, err)
}
defer r.Body.Close()
log.Printf("GET %s: %q", url, r.Status)
if r.StatusCode != http.StatusOK {
log.Fatalf("http error: %q", r.Status)
}
zr, err := gzip.NewReader(r.Body)
if err != nil {
log.Fatalf("error opening gzip package index: %v", err)
}
tr := tar.NewReader(zr)
for {
hdr, err := tr.Next()
if err == io.EOF {
log.Fatalf("APKINDEX header not found")
}
if err != nil {
log.Fatalf("error reading tar header: %v", err)
}
if hdr.Name == "APKINDEX" {
break
}
}
scanner := bufio.NewScanner(tr)
var (
pkg string
v string
)
for scanner.Scan() {
l := scanner.Text()
parts := strings.SplitN(l, ":", 2)
if len(parts) != 2 {
continue
}
switch parts[0] {
case "P":
pkg = parts[1]
case "V":
v = parts[1]
versions[pkg] = v
case "D":
deps := strings.Split(parts[1], " ")
depends[pkg] = deps
depends[pkg+"="+v] = deps
case "p":
for _, so := range strings.Split(parts[1], " ") {
parts := strings.SplitN(so, "=", 2)
rprovides[parts[0]] = pkg + "=" + v
rprovides[so] = pkg + "=" + v
}
}
}
if err := scanner.Err(); err != nil {
log.Fatalf("error reading package index: %v", err)
}
pkgs := map[string]string{}
for _, p := range flag.Args() {
deepDeps(pkgs, p)
}
for k, v := range pkgs {
log.Println(k + "=" + v)
}
downloadPkgs(pkgs)
}
func deepDeps(deps map[string]string, pkg string) {
deps[pkg] = versions[pkg]
for _, p := range depends[pkg] {
parts := strings.SplitN(p, ":", 2)
if parts[0] == "so" {
p = rprovides[p]
}
parts = strings.SplitN(p, "=", 2)
var (
v = ""
)
if len(parts) == 2 {
p = parts[0]
v = parts[1]
}
if vv := deps[p]; vv != "" && v != "" && v != vv {
log.Fatalf("deps conflict: %q %q %q", p, v, vv)
}
deepDeps(deps, p)
}
}
func downloadPkgs(pkgs map[string]string) {
tw := tar.NewWriter(os.Stdout)
defer func() {
if err := tw.Close(); err != nil {
log.Fatalf("error finalizing archive: %v", err)
}
}()
for p, v := range pkgs {
m := strings.TrimLeft(*mirror, "/")
url := fmt.Sprintf("%s/%s-%s.apk", m, p, v)
r, err := http.Get(url)
if err != nil {
log.Fatalf("error making GET %s: %v", url, err)
}
defer r.Body.Close()
log.Printf("GET %s: %q", url, r.Status)
if r.StatusCode != http.StatusOK {
log.Fatalf("http error: %q", r.Status)
}
zr, err := gzip.NewReader(r.Body)
if err != nil {
log.Fatalf("error reading gzip response: %v", err)
}
tr := tar.NewReader(zr)
for {
hdr, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("error reading tar header: %v", err)
}
if strings.HasPrefix(hdr.Name, ".SIGN.RSA") || hdr.Name == ".PKGINFO" {
continue
}
if err := tw.WriteHeader(hdr); err != nil {
log.Fatalf("error writing header %q: %v", hdr.Name, err)
}
if _, err := io.Copy(tw, tr); err != nil {
log.Fatalf("error writing body: %q: %v", hdr.Name, err)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment