2017-11-18 4 views
0

Ich portiere eine alte .NET-Web-API-Anwendung zur Ausführung auf Heroku in einem Docker-Container. Ich benutze dazu ein Mono-Bild.Zugriff auf X-Server über einen Docker-Container auf Heroku

Hier ist meine 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 

Ziemlich einfach, die neuesten Mono Bild verwenden, um die Quelle zu kopieren, die NuGet Pakete wiederherzustellen, die Lösung erstellen und auszuführen. Die $ PORT-Umgebungsvariable wird von Heroku oder standardmäßig 5000 für meine lokale Entwicklungsumgebung gesetzt.

Alles funktioniert gut, außer einem bestimmten API-Controller, der einen PDF-Bericht generiert. Der Bericht wird von PdfSharp generiert, das für das erforderliche Rendering von der System.Drawing-Assembly abhängig ist. Dies bedeutet jedoch eine Abhängigkeit von der Anzeige.

Wenn ich diesen Controller aufrufen, um einen Bericht zu generieren, erhalte ich den folgenden Fehler.

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

Ich benötige Zugriff auf einen X-Server, um das erforderliche Rendering durchzuführen. Ich habe viele Dinge ausprobiert, stecke aber immer an diesem Fehler fest.

Antwort

0

Es funktioniert durch die Installation von Xvfb (virtual framebuffer), einem Display-Server, der das X11-Display-Server-Protokoll implementiert. Sie können sich die aktualisierte Dockerfile unten ansehen.

Bemerkung: Abgesehen von dem Display-Server gab es mehr Probleme mit PDFSharp auf Mono laufen zu lassen. Ich musste auch die Apt-Quellen aktualisieren und die Microsoft Core Fonts installieren, da die Berichte, die ich generiere, sie verwenden. Ich musste auch eine modifizierte Version von PDFSharp verwenden, die weiß, wie man die Fonts findet. Zum Glück war dies bereits für mich getan:

https://github.com/daniellor/PDFsharp

Der entsprechende Code ist hier:

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

Ein bisschen hacky und man könnte es ändern müssen das Setup anpassen, aber es funktioniert die Arbeit. Erstellen Sie einfach ein MonoRelease-Build und verweisen Sie auf diese Baugruppe, und Sie können loslegen.

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 
Verwandte Themen