SpringBoot + Indy-SDK 镜像搭建

4/25/2021 docker区块链

Springboot + Indy-SDK 镜像搭建

我们项目一直用的一个 SpringBoot Docker 镜像: wattazoum/springboot-runner
DockerHub 地址: https://hub.docker.com/r/wattazoum/springboot-runner (opens new window)
简单介绍:

Based on openjdk:8u121-jre-alpine (opens new window) docker image.
This image is more that just a Spring Boot (opens new window) runner. I can launch any java command.
I created it first because I needed to launch a spring boot application in a container.
But I didn't want to:

  • recreate an image for every version
  • customize the docker run command per environment.

因为我们 凭证管理系统App 的接口中需要用到 indy-sdk ,但是官方并没有提供在 docker 容器中安装配置的方法,只能自己去自定义镜像。

参考已有的 indy-sdk Dockerfile:

FROM ubuntu:bionic
MAINTAINER author
RUN apt-get update
RUN apt-get install -y gnupg2 software-properties-common
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CE7709D068DB5E88
RUN add-apt-repository "deb https://repo.sovrin.org/sdk/deb bionic stable"
RUN apt-get update
RUN apt-get install -y libindy
 ... 省略一些 Python 命令
RUN adduser indy
RUN echo 'indy:indypasswd' | chpasswd
RUN mkdir /app
RUN chown -R indy /app
USER indy
WORKDIR /app
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

可以看到这个镜像是基于 ubuntu:bionic ,那么我们就可以在 Ubuntu Os 镜像的基础上安装配置 Java 环境,集成已有的 SpringBoot-Runner,那么,我们就需要先分析 springboot-runner 的实现。

# 解析 wattazoum/springboot-runner

Github 地址:https://github.com/wattazoum/docker-springboot-runner (opens new window)

可以看到,核心文件就是一个 Dockerfile 和一个脚本文件 entrypoint.sh

FROM openjdk:8u121-jre-alpine
MAINTAINER Oumar Aziz OUATTARA (wattazoum)

RUN apk update && apk add fontconfig ttf-dejavu

RUN adduser -S -u 1000 springboot && \
    mkdir -p /app && \
    chown -R springboot /app

ADD entrypoint.sh /usr/local/bin/

USER springboot

WORKDIR /app

VOLUME /app
EXPOSE 8080

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh
set -e

# In case the user wants only to use java with options
if [ $# -gt 0 ]
then
    exec java $@
    exit 0
fi

# Behavior when using the /app folder
#
# In the setenv.sh file you may define the following environment
# variables
#
# JAVA_OPTS : a string containing the list of java options to 
#             pass to the java command.
#             eg. JAVA_OPTS="-Xmx1g -Dfile.encoding=utf8"
# APP_ARGS

SETENV_FILE=/app/setenv.sh

if [ -r $SETENV_FILE ]
then
    source $SETENV_FILE
fi


TMP_JARS_LIST=/tmp/jars_list 

find /app -maxdepth 1 -regex '.*.[jw]ar$' > $TMP_JARS_LIST
nb_jars=$(cat $TMP_JARS_LIST | wc -l)
if [ $nb_jars -gt 1 ]
then
    echo 'ERROR: You may only have one jar/war in the /app folder'
    echo '==================================================='
    cat $TMP_JARS_LIST
    exit 1
elif [ $nb_jars -eq 0 ]
then
    echo 'ERROR: There should be one and only one jar/war in the /app folder'
    echo '=============================================================='
    exit 1
else 
    CMD="java $JAVA_OPTS -jar $(cat $TMP_JARS_LIST) $APP_ARGS"
    echo "Launching the following command:"
    echo "  |"
    echo '  `->  '"$CMD"
    echo 
    exec $CMD
fi

exit 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  • 通过 source 命令,写入配置文件的内容到环境变量
  • 判断 /app 目录下 jar 包的数量
    • 多于 1 个,报错
    • 少于 1 个,报错
  • 执行 java -jar 命令

核心就是 Java 环境和 java -jar CMD

# 集成 springboot-runner 和 indy-sdk

基于 Ubuntu 镜像,安装 indy-sdk、安装 Jdk 、执行 java -jar CMD

目录结构: image.png /app-docker

  • /app
  • docker-compose.yml
  • Dockerfile
  • entrypoint.sh

entrypoint.sh 脚本文件复制上面 runner 的即可;

Dockerfile 配置:

FROM ubuntu:bionic
MAINTAINER dongzhang@gaoshan.co
RUN apt-get update
RUN apt-get install -y gnupg2 software-properties-common
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CE7709D068DB5E88 \
 && add-apt-repository "deb https://repo.sovrin.org/sdk/deb bionic stable" \
 && apt-get update \
 && apt-get install -y libindy

RUN apt-get install -y openjdk-8-jdk \
 && java -version

RUN adduser indy \
 && echo 'indy:indypasswd' | chpasswd \
 && mkdir /app \
 && chown -R indy /app

ADD entrypoint.sh /usr/local/bin/

RUN chmod +x /usr/local/bin/entrypoint.sh

USER indy

WORKDIR /app

VOLUME /app
EXPOSE 8080

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

docker-compose.yml 配置参考:

version: '3'
services:
  cert-app-center:
    build:
      context: .
      dockerfile: Dockerfile
    image: wattazoum/springboot-runner-local
    container_name: cert-app-center
  #  restart: always
    tty: true
    stdin_open: true
    ports:
      - 8084:8084
    volumes:
      - ./cert-app-center/logs:/mnt/logs
      - ./cert-app-center:/app
      - /etc/localtime:/etc/localtime
    environment:
      - 'TZ="Asia/Shanghai"'
    networks:
      - default
networks:
  default:
    external:
      name: cert_default

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 遇到的问题

# permission denied: unknown

OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "/usr/local/bin/entrypoint.sh": permission denied: unknown

解决方案: Dockerfile 增加 RUN chmod +x /usr/local/bin/entrypoint.sh

# source: not found

解决方案: 修改 entrypoint.sh 文件头 #!/bin

例如,我装java,解压之后配置环境变量,因为用的是Docker ubuntu自带的终端执行的命令,所以修改的是~/.bashrc文件,修改完了之后要用source命令生效: Source ~/.bashrc:报:/bin/sh: 28: source: not found 查了下,说是sh 和 bash 是不同的 shell,sh 中没有 source 命令,解决的方法是: /bin/bash -c "source 要执行的原内容” 若是要执行shell脚本中的该命令,则在 shell 脚本的第一行加上一行 "#!/bin/bash" 即可。这一行指定了shell 脚本解释器的路径,而且这个指定路径 只能放在文件的第一行。

# 启动报错,无法连接 nacos mysql 等其他容器

解决方案: 修改了 docker-compose.yml ,增加 networks 相关的配置

原因尚不清楚,还有很多需要学习的;