2017-11-18 280 views
0

我將一箇舊的.NET Web API應用程序移植到Docker容器中的Heroku上運行。我正在使用單色圖像。從Heroku的Docker容器中訪問X-Server

這裏是我的Dockerfile:

FROM mono:latest 
EXPOSE 5000 
ENV PORT 5000 
ADD ./ /api 
WORKDIR /api 
RUN nuget restore -NonInteractive 
RUN msbuild webapi.sln /p:Configuration=Release 
CMD mono /api/MyProject/bin/Release/MyProject.exe port:$PORT 

非常簡單,採用最新的立體圖像,複製源,恢復的NuGet軟件包,構建解決方案,並運行它。 $ PORT環境變量由Heroku設置,或者我的本地開發環境默認爲5000。

這一切都很好,除了一個特定的API控制器生成PDF報告。該報告由PdfSharp生成,它依賴於System.Drawing程序集以進行必要的渲染。但是這意味着依賴於顯示。

當我調用該控制器生成報告時,出現以下錯誤。

Could not open display (X-Server required. Check your DISPLAY environment variable). 

我需要訪問X-Server才能進行必要的渲染。我嘗試了很多東西,但總是堅持這個錯誤。

回答

0

通過安裝Xvfb(虛擬幀緩衝區),一個實現X11顯示服務器協議的顯示服務器,得到它的工作。你可以看看下面更新的Dockerfile。

備註:除了顯示服務器之外,還有更多使PDFSharp在Mono上運行的問題。我還必須更新apt源並安裝Microsoft Core Fonts,因爲我生成的報告使用它們。 我也必須使用知道如何定位字體的PDFSharp的修改版本。幸運的是,這已經爲我做的:

https://github.com/daniellor/PDFsharp

相關的代碼是在這裏:

https://github.com/daniellor/PDFsharp/blob/master/src/PdfSharp/Fonts/FontLocalizator.cs

有點哈克,你可能需要修改,以滿足您的設置,但它確實工作。只需創建一個MonoRelease版本並引用該程序集,就可以開始使用了。

Dockerfile

FROM mono:latest 

# Update the sources.list for apt-get so it knows where to download the Microsoft Core fonts. 
RUN echo "deb http://gce_debian_mirror.storage.googleapis.com wheezy contrib non-free" >> /etc/apt/sources.list \ 
    && echo "deb http://gce_debian_mirror.storage.googleapis.com wheezy-updates contrib non-free" >> /etc/apt/sources.list \ 
    && echo "deb http://security.debian.org/ wheezy/updates contrib non-free" >> /etc/apt/sources.list 

# Install Xvfb and the Microsoft core fonts 
RUN apt-get update 
RUN apt-get install -y xvfb ttf-mscorefonts-installer 

# Configure Xvfb as a daemon. 
ADD xvfb.init /etc/init.d/xvfb 
RUN chmod +x /etc/init.d/xvfb 
RUN update-rc.d xvfb defaults 

EXPOSE 5000 
ENV PORT 5000 
ADD ./ /api 
WORKDIR /api 
RUN nuget restore -NonInteractive 
RUN msbuild webapi.sln /p:Configuration=Release 

# Start Xvfb and the Web Api 
CMD (service xvfb start; export DISPLAY=:10; mono /api/MyProject/bin/Release/MyProject.exe port:$PORT) 

xvfb.init

#!/bin/bash 
# 
# /etc/rc.d/init.d/xvfbd 
# 
# chkconfig: 345 95 28 
# description: Starts/Stops X Virtual Framebuffer server 
# processname: Xvfb 
# 

[ "${NETWORKING}" = "no" ] && exit 0 

PROG="/usr/bin/Xvfb" 
PROG_OPTIONS=":10 -ac" 
PROG_OUTPUT="/tmp/Xvfb.out" 

case "$1" in 
    start) 
     echo -n "Starting : X Virtual Frame Buffer " 
     $PROG $PROG_OPTIONS>>$PROG_OUTPUT 2>&1 & 
     disown -ar 
     ;; 
    stop) 
     echo -n "Shutting down : X Virtual Frame Buffer" 
     killproc $PROG 
     RETVAL=$? 
     [ $RETVAL -eq 0 ] && /bin/rm -f /var/lock/subsys/Xvfb/var/run/Xvfb.pid 
     echo 
     ;; 
    restart|reload) 
     $0 stop 
     $0 start 
     RETVAL=$? 
     ;; 
    status) 
     status Xvfb 
     RETVAL=$? 
     ;; 
    *) 
    echo $"Usage: $0 (start|stop|restart|reload|status)" 
    exit 1 
esac 

exit $RETVAL