1. 目的
在做分布式项目过程中,用到了rocksdb做数据的永久化,在测试多个节点时,需要用到docker来完成部署,因此需要制作docker镜像。这篇文章记录了若干种制作docker镜像的方案,记录了踩坑的过程。
2.配置环境
系统环境
//golang版本
go version go1.19.2 darwin/arm64
// docker,docker-compose的环境
Client:
Cloud integration: v1.0.29
Version: 20.10.21
API version: 1.41
Go version: go1.18.7
Git commit: baeda1f
Built: Tue Oct 25 18:01:18 2022
OS/Arch: darwin/arm64
Context: default
Experimental: true
Server: Docker Desktop 4.15.0 (93002)
Engine:
Version: 20.10.21
API version: 1.41 (minimum version 1.12)
Go version: go1.18.7
Git commit: 3056208
Built: Tue Oct 25 17:59:41 2022
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: 1.6.10
GitCommit: 770bd0108c32f3fb5c73ae1264f7e503fe7b2661
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0
Docker Compose version v2.13.0
//宿主机rocksdb配置
brew info rocksdb
==> rocksdb: stable 7.8.3 (bottled), HEAD
Embeddable, persistent key-value store for fast storage
https://rocksdb.org/
/opt/homebrew/Cellar/rocksdb/7.8.3 (143 files, 41.3MB) *
Poured from bottle on 2022-12-20 at 18:19:18
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/rocksdb.rb
License: GPL-2.0-only or Apache-2.03.环境安装
需要安装golang、docker、rocksdb(mac可以直接homebrew安装,linux则须先clone再自行编译)
4. 编译镜像制作
值得一提的是,由于本机是mac,而程序运行需要跑在linux系统上,因此在本机编译linux可执行文件需要golang的交叉编译。
4.1 本机交叉编译
使用MacOs的朋友可以看一下下面的这个文章,这里面揭示了一些可能出现的问题,在一开始的时候我也曾经想过在本机交叉编译后,直接复制到运行用的镜像里,但是一切都是十分顺利,直到需要编译rocksdb的时候,homebrew下载的交叉编译工具(mac原生的库有些不支持,就如下面的链接里的一样),一直提示找不到rocksdb需要用到的几个依赖。
4.2 在docker镜像中编译
最后经过几个小时的试错,最终决定在docker镜像里编译,再复制到运行镜像中运行。我们需要用到俩个文件
Makefile
.PHONY: build clean docker-build
BINARY=main
GO_VER = 1.19
ALPINE_VER ?= 3.16
VER = 1.0
BUILD_CONTEXT=.
build:
@echo "compiling code ..."
CGO_CFLAGS="-I/usr/local/rocksdb/ -I/usr/include/" \
CGO_LDFLAGS="-L/usr/local/rocksdb/lib -L/usr/lib -lrocksdb -lstdc++ -lm -lz -lbz2 -lsnappy -llz4 -lzstd -static -fpic" \
go build
@echo "compiled successfully in $(BUILD_CONTEXT)/$(BINARY)"
docker-build :
@echo "Building Docker image ..."
@docker build -f . \
--build-arg GO_VER=$(GO_VER) \
--build-arg ALPINE_VER=$(ALPINE_VER) \
-t $(BINARY):$(VER) $(BUILD_CONTEXT)
clean:
@if [ -f $(BINARY) ] ; then rm $(BUILD_CONTEXT)/$(BINARY) ; fidockerfile
ARG GO_VER
ARG ALPINE_VER
FROM alpine:${ALPINE_VER} as base
RUN apk add --no-cache tzdata
# FROM golang:${GO_VER}-alpine${ALPINE_VER} as golang
# RUN apk add --no-cache \
# bash \
# binutils-gold \
# gcc \
# git \
# make \
# musl-dev
# RUN apk add --update --no-cache build-base linux-headers git cmake bash perl #wget mercurial g++ autoconf libgflags-dev cmake bash
# RUN apk add --update --no-cache zlib zlib-dev bzip2 bzip2-dev snappy snappy-dev lz4 lz4-dev zstd zstd-dev
# # installing latest gflags
# RUN cd /tmp && \
# git clone https://github.com/gflags/gflags.git && \
# cd gflags && \
# mkdir build && \
# cd build && \
# cmake -DBUILD_SHARED_LIBS=1 -DGFLAGS_INSTALL_SHARED_LIBS=1 .. && \
# make install && \
# cd /tmp && \
# rm -R /tmp/gflags/
# # Install Rocksdb
# RUN cd /tmp && \
# git clone https://github.com/facebook/rocksdb.git && \
# cd rocksdb && \
# git checkout v7.8.3 && \
# make shared_lib && \
# mkdir -p /usr/local/rocksdb/lib && \
# mkdir /usr/local/rocksdb/include && \
# cp librocksdb.so* /usr/local/rocksdb/lib && \
# cp /usr/local/rocksdb/lib/librocksdb.so* /usr/lib/ && \
# cp -r include /usr/local/rocksdb/ && \
# cp -r include/* /usr/include/ && \
# rm -R /tmp/rocksdb/
FROM golang-rocksdb-sdk as golang
ADD . /src
WORKDIR /src
RUN make build
FROM base
WORKDIR /apps
COPY --from=golang /src/main /apps
EXPOSE 8000
ENTRYPOINT ["/apps/main"]在main.go文件下,执行make docker-build 。就能自动执行镜像。但是前提是,需要编译一个制作镜像用的镜像
我们需要一下指令
mkdir golang-rocksdb
cd golang-rocksdb
docker build -t golang-rocksdb .编译以下docker镜像
# FROM alpine:3.16 as builder
# RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >>/etc/apk/repositories
# RUN apk add --update --no-cache build-base linux-headers git perl \
# cmake bash zlib zlib-dev bzip2 bzip2-dev snappy snappy-dev lz4 lz4-dev \
# zstd@testing zstd-dev@testing libtbb-dev@testing libtbb@testing
# RUN cd tmp && \
# git clone https://github.com/gflags/gflags.git && \
# cd gflags && \
# mkdir build && \
# cd build && \
# cmake -DBUILD_SHARED_LIBS=1 -DGFLAGS_INSTALL_SHARED_LIBS=1 .. && \
# make install && \
# cd ../ \
# rm -R gflags/
# RUN cd /tmp && \
# git clone https://github.com/facebook/rocksdb.git && \
# cd rocksdb && \
# git checkout v7.8.3 && \
# make static_lib && \
# mkdir -p /usr/local/rocksdb/lib && \
# mkdir /usr/local/rocksdb/include && \
# cp librocksdb.so* /usr/local/rocksdb/lib && \
# cp /usr/local/rocksdb/lib/librocksdb.so* /usr/lib/ && \
# cp -r include /usr/local/rocksdb/ && \
# cp -r include/* /usr/include/ && \
# rm -R /tmp/rocksdb/
# FROM golang:1.19-alpine3.16
FROM golang:1.19-alpine3.16 as golang
RUN apk add --no-cache \
bash \
binutils-gold \
gcc \
git \
make \
musl-dev
RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >>/etc/apk/repositories && \
apk add --update --no-cache pkgconfig tzdata ca-certificates gcc openssl cmake linux-headers \
alpine-sdk build-base libc-dev musl-dev libstdc++ libsodium-dev perl \
zlib zlib-static \
snappy snappy-dev snappy-static \
zstd@testing zstd-dev@testing zstd-static \
bzip2 bzip2-dev bzip2-static \
lz4 lz4-dev lz4-static \
libtbb-dev@testing libtbb@testing
# installing latest gflags
RUN cd /tmp && \
git clone https://github.com/gflags/gflags.git && \
cd gflags && \
mkdir build && \
cd build && \
cmake -DBUILD_SHARED_LIBS=1 -DGFLAGS_INSTALL_SHARED_LIBS=1 .. && \
make install && \
cd /tmp && \
rm -R /tmp/gflags/
# Install Rocksdb
RUN cd /tmp && \
git clone https://github.com/facebook/rocksdb.git && \
cd rocksdb && \
git checkout v7.8.3 && \
make static_lib && \
mkdir -p /usr/local/rocksdb/lib && \
mkdir /usr/local/rocksdb/include && \
cp librocksdb.* /usr/local/rocksdb/lib && \
cp /usr/local/rocksdb/lib/librocksdb.* /usr/lib/ && \
cp -r include /usr/local/rocksdb/ && \
cp -r include/* /usr/include/ && \
rm -R /tmp/rocksdb/
该代码是我从网上找到的dockerfile改过来的,因为网上所使用的原版的rocksdb是旧版的,一些目录不适配。
因此需要手动修改,这里选择了golang1.19,alpine3.6,截止至本文写作时间之前,alpine3.7已经出了,但是因为apk有些包没有更新(比如zstd),因此选择了一个更稳定的版本。
最后,编译完成是这样的。
自行编写docker-compose文件,就可以启动自己的服务了。