Home .NET FastReport.Mono.Part 2: Web Report in a Docker Container

FastReport.Mono.Part 2: Web Report in a Docker Container

by admin

FastReport.Mono.Part 2: Web Report in a Docker Container
In the previous part of I told you how to run the demo Web-report FastReport.Mono. Now, I suggest to take it to the next level and "wrap" all necessary components in Docker containers.

Understand, in heaven all they talk about is the sea. How infinitely beautiful it is…

Everyone and everywhere has been talking about Docker for the last few years, because containers are classy, trendy and sexy youthful. Many developers and administrators use Docker for business and no apparent need for it. But, if you really need it and are interested, welcome under the hood. Unlike the first part, there will be a maximum of text and a minimum of images.
As already mentioned, we may need 2 containers for FastReport.Mono to work properly :

  • Apache 2.4 container
  • container with X-server

We create both containers based on the debian:stretch image from the Docker repository.

FRMono container

The first container, as already mentioned, will contain Apache 2.4. In addition, we will immediately add Mono and FastRepor to it when we build it.
Basically, nothing prevents to extend Dockerfileand organize automatic installation of some Oracle Instant Client, but since this article is dedicated exactly to Web Report Demo – we don’t need it.
Dockerfile

FROM debian:stretchENV TZ Europe/MoscowENV DEBIAN_FRONTEND noninteractiveENV DISPLAY:1WORKDIR /RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ > /etc/timezoneRUN echo "nameserver 8.8.8.8" > /etc/resolv.confRUN ["mkdir", "-p", "/opt/fastreport/htdocs/bin"]RUN apt-get update \ apt-get -y install apt-utils \ apt-get -y install unzip \ apt-get -y install mono-complete mono-xsp apache2 libapache2-mod-mono# Apache setupCOPY 001-mono.conf/etc/apache2/sites-available/001-mono.confRUN /usr/sbin/update-rc.d apache2 disable \ /usr/sbin/a2dismod mod_mono_auto \ /usr/sbin/a2dissite 000-default \ /usr/sbin/a2ensite 001-mono# FastReport.Mono setup# Download official DemoADD https://www.fastreport.ru/public_download/frmono_demo.zip /tmp/frmono_demo.zip# Or add from local filesystem#COPY frmono_demo.zip /tmp/frmono_demo.zip# Extract and copy to destinationsRUN ["unzip", "/tmp/frmono_demo.zip", "-d", "/tmp/frmono.demo"]RUN cp -rp /tmp/frmono.demo/Demos/C#/Web/* /opt/fastreport/htdocsRUN cp /tmp/frmono.demo/FastReport.*.dll /opt/fastreport/htdocs/binRUN chown -R www-data:www-data /opt/fastreport# Volume for X11 unix socketVOLUME /tmp/.X11-unix# Start Apache in foreground to prevent container exitCMD ["/usr/sbin/apachectl", "-DFOREGROUND"]

There is nothing complicated or tricky about it. The main thing to pay attention to is not to run Apache as a background process, but to put it in the foreground. Otherwise, the container will stop working right after it is started.
The virtual host configuration file for Apache is basically a stripped-down version of the one in the first part of this publication. However, there are some differences. This is because we will be using a slightly different directory structure (placing the libraries in the bin directory).
Any particular difference in these approaches, I personally do not see. Besides, you can safely use port 80 in the container.
001-mono.conf

<VirtualHost *:80>DocumentRoot "/opt/fastreport/htdocs"<IfModule mod_mono.c>MonoUnixSocket FrSite /tmp/.mod_mono_serverMonoServerPath FrSite /usr/bin/mod-mono-server4MonoPath FrSite /usr/lib/mono/4.5:/usr/lib:/usr/lib/mono/4.0AddMonoApplications FrSite "/:/opt/fastreport/htdocs"MonoAutoApplication DisabledMonoDocumentRootDir /opt/fastreport/htdocsMonoDebug falseMonoSetEnv FrSite DISPLAY=:1;HOME=/opt/fastreportAddHandler mono .aspx .ascx .asax .ashx .config .cs .asmx .axd</IfModule><Directory "/opt/fastreport/htdocs">Require all grantedOptions Indexes FollowSymLinks MultiViewsAllowOverride All<IfModule mod_mono.c>SetHandler monoMonoSetServerAlias FrSiteDirectoryIndex Default.aspx</IfModule></Directory><Directory "/opt/fastreport/htdocs/bin">Require all denied</Directory></VirtualHost>

Start the assembly process :

docker build -t debian-stretch-mono:latest .

Container X11Dummy

In the first part of of this series, I already mentioned that to use System.Windows.Forms you need an X server. Since the container with Apache, Mono and FastReport doesn’t have "X’s", we need to get them from somewhere.
Two options are possible :

  • to use the X-server which is running in the host OS
  • Use a separate container with the X-server

The first option will require different configuration, depending on the OS you use. In fact, in Linux it might be, for example, X.org , on Mac OS. XQuartz , and in Windows you have to deliver Xming
The second option is more in line with the Docker concept and allows you to create an easily portable and OS-independent host system. Interaction between containers can be done via tcp or unix socket. In my opinion, the unix socket option is an excellent one for this task.
Dockerfile

FROM debian:stretchENV TZ Europe/MoscowENV DEBIAN_FRONTEND noninteractiveENV DISPLAY :1RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ > /etc/timezoneRUN echo "nameserver 8.8.8.8" > /etc/resolv.confRUN apt-get update \ apt-get -y install apt-utils \ apt-get -y install xserver-xorg-video-dummyx11-appsVOLUME /tmp/.X11-unixCOPY xorg.mini.conf/etc/X11/xorg.confCMD /usr/bin/Xorg -noreset +extension GLX +extension RANDR +extension RENDER -logfile /tmp/xdummy.log -config /etc/X11/xorg.conf $DISPLAY

If you examine the Docerfile under the spoiler carefully, two things are worth noting. The first is the use of the video driver from the xserver-xorg-video-dummy "Empty" driver that tells the X-server that it outputs an image, but doesn’t actually do anything.
The second is to set the environment variable DISPLAY to a value other than what you are used to from all sorts of instructions :0. This is only a precautionary measure if you decide to put a UNIX socket through /tmp of the host OS.
The X server configuration file, a variation on the this config walking around with various modifications all over the net. I’ve got a very long version with lots of Modeline’s (alas, I couldn’t remember the source) and I tried to compress it as much as possible (although I think you can still).
xorg.mini.conf

Section "ServerFlags"Option "DontVTSwitch" "true"Option "AllowMouseOpenFail" "true"Option "PciForceNone" "true"Option "AllowEmptyInput" "true"Option "AutoEnableDevices" "false"Option "AutoAddDevices" "false"EndSectionSection "Device"Identifier "dummy_videocard"Driver "dummy"DacSpeed 600Option "ConstantDPI" "true"VideoRam 256000EndSectionSection "Monitor"Identifier "dummy_monitor"HorizSync 1.0 - 2000.0VertRefresh 1.0 - 200.0Modeline "1920x1080" 23.53 1920 1952 2040 2072 1080 1106 1108 1135Modeline "1280x1024" 31.50 1280 1312 1424 1456 1024 1048 1052 1076Modeline "1280x720" 59.42 1280 1312 1536 1568 720 735 741 757Modeline "1024x768" 18.71 1024 1056 1120 1152 768 786 789 807EndSectionSection "Screen"Identifier "dummy_screen"Device "dummy_videocard"Monitor "dummy_monitor"DefaultDepth 24SubSection "Display"Viewport 0 0Depth 8Modes "1920x1080" "1280x1024" "1280x800" "1024x768"Virtual 8192 4096EndSubSectionSubSection "Display"Viewport 0 0Depth 16Modes "1920x1080" "1280x1024" "1280x800" "1024x768"Virtual 8192 4096EndSubSectionSubSection "Display"Viewport 0 0Depth 24Modes "1920x1080" "1280x1024" "1280x800" "1024x768"Virtual 8192 4096EndSubSectionSubSection "Display"Viewport 0 0Depth 30Modes "1920x1080" "1280x1024" "1280x800" "1024x768"Virtual 8192 4096EndSubSectionEndSectionSection "ServerLayout"Identifier "dummy_layout"Screen "dummy_screen"EndSection

Gathering :

docker build -t debian-stretch-x11dummy:latest .

Running with Docker-compose

For easy service management, the docker-compose In the startup process, we need to :

  • to put "outside" Apache from the container with FastReport.Mono
  • "Route" unix socket X server from x11dummy container to frmono container

Based on the above requirements, we get the minimum required docker-compose.yml.
docker-compose.yml

version: "2"services:fastreport:container_name: frmonoimage: debian-stretch-mono:latestvolumes:- ./.x11-unixsoc:/tmp/.X11-unixports:- "127.0.0.1:8085:80"xorg:container_name: x11dummyimage: debian-stretch-x11dummy:latestvolumes:- ./.x11-unixsoc:/tmp/.X11-unix

N.B. If you are not familiar with YAML , note that the formatting is done by spaces
Since an unix socket is essentially a file, we use connectable volumes which allow the container to communicate with the host. With this approach, both containers will use the .x11-unixsoc directory in the startup directory to communicate.
Run and check :

docker-compose up

And, as a friend of mine likes to say, "the icing on the cake": automating the startup of the OS with Systemd. Everything is done in two simple steps. First, it is necessary, and sufficient, to create a file /etc/system.d/system/docker-frmono.service, the approximate content of which is shown under the spoiler. Why approximate? At a minimum, you need to change the paths, according to the location of your chosen configuration files and the installation location of docker-compose.
docker-frmono.service

[Unit]Description=FastReport DockerRequires=docker.serviceAfter=docker.service[Service]Restart=alwaysExecStart=/usr/local/bin/docker-compose -f /opt/frdocker/docker-compose.yml startExecStop=/usr/local/bin/docker-compose -f /opt/frdocker/docker-compose.yml stop[Install]WantedBy=multi-user.target

Second, register the service in the system and "enable" it :

systemctl daemon-reloadsystemctl enable docker-frmono

P.S. It is possible that in the process of experimentation, you have accumulated a certain number of "crooked" images. You can clean it up as follows :

docker images | grep "<none> " | awk '{split($0, a, " ");print a[3];}' | xargs -I{} docker rmi "{}"

All of the conifiguration files used in this article are available at github

You may also like