diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..54da1fe --- /dev/null +++ b/Dockerfile @@ -0,0 +1,108 @@ +# use builder image to compile ledisdb (without GCO) +FROM golang:1.9-stretch as builder + +ENV LEDISDB_VERSION v0.6 + +ENV LEVELDB_VERSION 47cb9e2a211e1d7157078ba7bab536beb29e56dc +ENV ROCKSDB_VERSION 5.8.6 +ENV GOSU_VERSION 1.10 + + + +WORKDIR /build + +RUN apt-get update && \ + apt-get install -y \ + ca-certificates \ + wget \ + gcc-6 \ + g++-6 \ + build-essential \ + libsnappy1v5 \ + libsnappy-dev \ + libgflags-dev + +# get LedisDB +RUN wget -O ledisdb-src.tar.gz "https://github.com/siddontang/ledisdb/archive/$LEDISDB_VERSION.tar.gz" && \ + tar -zxf ledisdb-src.tar.gz && \ + mkdir -p /go/src/github.com/siddontang/ && \ + mv ledisdb-$LEDISDB_VERSION /go/src/github.com/siddontang/ledisdb + +# build LevelDB +RUN wget -O leveldb-src.tar.gz "https://github.com/google/leveldb/archive/$LEVELDB_VERSION.tar.gz" && \ + tar -zxf leveldb-src.tar.gz && \ + cd leveldb-$LEVELDB_VERSION && \ + patch -p0 < /go/src/github.com/siddontang/ledisdb/tools/leveldb.patch && \ + make -j "$(nproc)" && \ + mkdir /build/lib && \ + mkdir -p /build/include/leveldb && \ + cp out-static/lib* /build/lib/ && \ + install include/leveldb/*.h /build/include/leveldb + + +# build RocksDB +RUN wget -O rocksdb-src.tar.gz "https://github.com/facebook/rocksdb/archive/v$ROCKSDB_VERSION.tar.gz" && \ + tar -zxf rocksdb-src.tar.gz && \ + cd rocksdb-$ROCKSDB_VERSION && \ + make static_lib -j "$(nproc)" && \ + mkdir -p /build/include/rocksdb && \ + cp librocksdb.a /build/lib/ && \ + install include/rocksdb/*.h /build/include/rocksdb + +ENV CGO_CFLAGS "-I/build/include" +ENV CGO_CXXFLAGS "-I/build/include" +ENV CGO_LDFLAGS "-L/build/lib -lsnappy" + +#build LedisDB +RUN export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/build/lib:/usr/lib && \ + export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/build/lib:/usr/lib && \ + mkdir -p /build/bin && \ + rm -rf /build/bin/* && \ + cd /go/src/github.com/siddontang/ledisdb && \ + GOGC=off go build -i -o /build/bin/ledis-server -tags "snappy leveldb rocksdb" cmd/ledis-server/* && \ + GOGC=off go build -i -o /build/bin/ledis-cli -tags "snappy leveldb rocksdb" cmd/ledis-cli/* && \ + GOGC=off go build -i -o /build/bin/ledis-benchmark -tags "snappy leveldb rocksdb" cmd/ledis-benchmark/* && \ + GOGC=off go build -i -o /build/bin/ledis-dump -tags "snappy leveldb rocksdb" cmd/ledis-dump/* && \ + GOGC=off go build -i -o /build/bin/ledis-load -tags "snappy leveldb rocksdb" cmd/ledis-load/* && \ + GOGC=off go build -i -o /build/bin/ledis-repair -tags "snappy leveldb rocksdb" cmd/ledis-repair/* + +# grab gosu for easy step-down from root +# https://github.com/tianon/gosu/releases +RUN set -ex; \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + chmod +x /usr/local/bin/gosu + + +# done building - now create a tiny image with a statically linked Ledis +FROM debian:stretch-slim + +COPY --from=builder /build/lib/* /usr/lib/ +COPY --from=builder /build/bin/ledis-* /bin/ +COPY --from=builder /go/src/github.com/siddontang/ledisdb/config/config-docker.toml /config.toml +COPY --from=builder /usr/local/bin/gosu /bin/ + +RUN groupadd -r ledis && \ + useradd -r -g ledis ledis && \ + mkdir /datastore && \ + chown ledis:ledis /datastore && \ + chmod 444 /config.toml && \ + gosu nobody true + +RUN apt-get update && \ + apt-get install -y --no-install-recommends libsnappy1v5 && \ + rm -rf /var/lib/apt/lists/* + +VOLUME /datastore + +ADD entrypoint.sh /bin/entrypoint.sh + +ENTRYPOINT ["entrypoint.sh"] + +EXPOSE 6380 11181 + +CMD ["ledis-server", "--config=/config.toml"] diff --git a/config/config-docker.toml b/config/config-docker.toml new file mode 100644 index 0000000..f37cf28 --- /dev/null +++ b/config/config-docker.toml @@ -0,0 +1,170 @@ +# LedisDB configuration + +# Server listen address +addr = "0.0.0.0:6380" + +# Unix socket permissions, 755 by default. +# Ignored for tcp socket. +addr_unixsocketperm = "0770" + +# Server http listen address, set empty to disable +http_addr = "0.0.0.0:11181" + +# Data store path, all ledisdb's data will be saved here +data_dir = "/datastore" + +# Set the number of databases. You can use `select dbindex` to choose a db. +# dbindex must be in [0, databases - 1]. +# Default databases is 16, maximum is 10240 now. +databases = 16 + +# Log server command, set empty to disable +access_log = "" + +# Set slaveof to enable replication from master, empty, no replication +# Any write operations except flushall and replication will be disabled in slave mode. +slaveof = "" + +# Readonly mode, slave server is always readonly even readonly = false +# for readonly mode, only replication and flushall can write +readonly = false + +# Choose which backend storage to use, now support: +# +# leveldb +# rocksdb +# goleveldb +# memory +# +db_name = "leveldb" + +# If not set, use data_dir/"db_name"_data +db_path = "" + +# Sync commit to disk if possible +# 0: no sync +# 1: sync every second +# 2: sync every commit +db_sync_commit = 0 + +# enable replication or not +use_replication = false + +# set connection buffer, you can increase them appropriately +# more size, more memory used +conn_read_buffer_size = 10240 +conn_write_buffer_size = 10240 + +# if connection receives no data after n seconds, it may be dead, close +# 0 to disable and not check +conn_keepalive_interval = 0 + +# checking TTL (time to live) data every n seconds +# if you set big, the expired data may not be deleted immediately +ttl_check_interval = 1 + +[leveldb] +# for leveldb and goleveldb +compression = false +block_size = 32768 +write_buffer_size = 67108864 +cache_size = 524288000 +max_open_files = 1024 +max_file_size = 33554432 + +[rocksdb] +# rocksdb has many many configurations, +# we only list little now, but may add more later. +# good luck! + +# 0:no, 1:snappy, 2:zlib, 3:bz2, 4:lz4, 5:lz4hc +compression = 0 +block_size = 65536 +write_buffer_size = 134217728 +cache_size = 1073741824 +max_open_files = 1024 +max_write_buffer_num = 6 +min_write_buffer_number_to_merge = 2 +num_levels = 7 +level0_file_num_compaction_trigger = 8 +level0_slowdown_writes_trigger = 16 +level0_stop_writes_trigger = 64 +target_file_size_base = 67108864 +target_file_size_multiplier = 1 +max_bytes_for_level_base = 536870912 +max_bytes_for_level_multiplier = 8 +disable_auto_compactions = false +disable_data_sync = false +use_fsync = false +background_theads = 16 +high_priority_background_threads = 1 +max_background_compactions = 15 +max_background_flushes = 1 +allow_os_buffer = true +enable_statistics = false +stats_dump_period_sec = 3600 +# dangerous to set true, write may got lost after a crash +# you can set true if replication opened, we may recover from replication log, +# but it is still not a easy work. +disable_wal = false +max_manifest_file_size = 20971520 + +[lmdb] +map_size = 524288000 +nosync = true + +[replication] +# Path to store replication information(write ahead log, commit log, etc.) +# if not set, use data_dir/rpl +path = "" + +# If sync is true, the new log must be sent to some slaves, and then commit. +# It will reduce performance but have better high availability. +sync = false + +# If sync is true, wait at last wait_sync_time milliseconds for slave syncing this log +wait_sync_time = 500 + +# If sync is true, wait at most min(wait_max_slave_acks, (n + 1) / 2) to promise syncing ok. +# n is slave number +# If 0, wait (n + 1) / 2 acks. +wait_max_slave_acks = 2 + +# store name: file, goleveldb +# change in runtime is very dangerous +store_name = "file" + +# Expire write ahead logs after the given days +expired_log_days = 7 + +# for file store, if 0, use default 256MB, max is 1G +max_log_file_size = 0 + +# for file store, if 0, use default 50 +max_log_file_num = 0 + +# for file store, use mmap for file read and write +use_mmap = true + +# Sync log to disk if possible +# 0: no sync +# 1: sync every second +# 2: sync every commit +sync_log = 0 + +# Compress the log or not +compression = false + +[snapshot] +# Path to store snapshot dump file +# if not set, use data_dir/snapshot +# snapshot file name format is dmp-2006-01-02T15:04:05.999999999 +path = "" + +# Reserve newest max_num snapshot dump files +max_num = 1 + +[tls] +enabled = false +certificate = "test.crt" +key = "test.key" \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..d726d87 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +# first arg is `-f` or `--some-option` +# or first arg is `something.toml` +if [ "${1#-}" != "$1" ] || [ "${1%.toml}" != "$1" ]; then + set -- /bin/ledis-server "$@" +fi + +# allow the container to be started with `--user` +if [ "$1" = 'ledis-server' -a "$(id -u)" = '0' ]; then + chown -R ledis /datastore + chown ledis:ledis /bin/ledis-* + exec gosu ledis "$0" "$@" +fi + +exec "$@" \ No newline at end of file