{
  "date": "2020-02-08T22:25:42",
  "slug": "running-sql-server-on-the-oracle-free-tier",
  "link": "https://www.dbi-services.com/blog/running-sql-server-on-the-oracle-free-tier/",
  "title": {
    "rendered": "Running SQL Server on the Oracle Free tier"
  },
  "content": {
    "rendered": "<h2>By Franck Pachot</h2>\n<p>The Oracle Cloud is not only for Oracle Database. You can create a VM running Oracle Linux with full root access to it, even in the free tier: a free VM that will be always up, never expires, with full ssh connectivity to a sudoer user, where you are able to tunnel any port. Of course, there are some limits that I&#8217;ve detailed in a <a href=\"https://medium.com/@FranckPachot/the-oracle-cloud-free-tier-37c27f3b1e19?source=friends_link&amp;sk=2233caa140b1f1501ad8874f18fd2197\" target=\"_blank\" rel=\"noopener noreferrer\">previous post</a>. But that is sufficient to run a database, given that you configure a low memory usage. For Oracle Database XE, <a href=\"https://blog.ora-600.pl/2019/09/27/how-to-install-oracle-xe-18c-in-oracle-cloud-free-tier/\" target=\"_blank\" rel=\"noopener noreferrer\">Kamil Stawiarski</a> mentions that you can just hack the memory test in the RPM shell script.<br />\nBut for Microsoft SQL Server, that&#8217;s a bit more complex because this test is hardcoded in the sqlservr binary and the solution I propose here is to intercept the call to the sysinfo() system call.<br />\n<!--more--><br />\nCreating a VM in the Oracle Cloud is very easy, here are the steps in one picture:<br />\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37075\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/oraclefreetierforsqlserver001.png\" alt=\"\" width=\"1024\" height=\"683\" /></p>\n<p>I&#8217;m connecting to the public IP Address with ssh (the public key is uploaded when creating the VM) and I&#8217;ll will run everything as root:</p>\n<pre><code>ssh opc@129.213.138.34\nsudo su -\ncat /etc/oracle-release</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37066\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-172455.jpg\" alt=\"\" width=\"1024\" height=\"135\" /></p>\n<p>I install docker engine (version 19.3 there)</p>\n<pre><code>yum install -y docker-engine</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37065\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-172733.jpg\" alt=\"\" width=\"1024\" height=\"483\" /></p>\n<p>I start docker</p>\n<pre><code>\nsystemctl start docker\ndocker info</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37064\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-172947.jpg\" alt=\"\" width=\"1024\" height=\"697\" /><br />\nI&#8217;ll use the latest SQL Server 2019 image built on RHEL</p>\n<pre><code>docker pull mcr.microsoft.com/mssql/rhel/server:2019-latest\ndocker images</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37063\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-173411.jpg\" alt=\"\" width=\"1024\" height=\"256\" /></p>\n<p>5 minutes to download a 1.5GB image. Now trying to start it.<br />\nThe nice thing (when I compare to Oracle) is that we don&#8217;t have to manually accept the license terms with a click-through process. I just mention that I have read and accepted them with: ACCEPT_EULA=Y</p>\n<p>I try to run it:</p>\n<pre><code>docker run \\\n -e \"ACCEPT_EULA=Y\" \\\n -e 'MSSQL_PID=Express' \\\n -p 1433:1433 \\\n -e 'SA_PASSWORD=**P455w0rd**' \\\n --name mssql \\\n mcr.microsoft.com/mssql/rhel/server:2019-latest</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37062\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-173451.jpg\" alt=\"\" width=\"1024\" height=\"228\" /></p>\n<p>There&#8217;s a hardcoded prerequisite verification to check that the system has at least 2000 MB of RAM. And I have less than one GB here in this free tier:</p>\n<pre><code>\nawk '/^Mem/{print $0,$2/1024\" MB\"}' /proc/meminfo\n</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37071\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-174805.jpg\" alt=\"\" width=\"1024\" height=\"137\" /></p>\n<p>Fortunately, there&#8217;s always a nice geek on the internet with an awesome solution: hack the sysinfo() system call with a LD_PRELOAD&#8217;ed wrapper : <a href=\"https://github.com/justin2004/mssql_server_tiny\" target=\"_blank\" rel=\"noopener noreferrer\">A Slightly Liberated Microsoft SQL Server Docker image</a></p>\n<p>Let&#8217;s get it:</p>\n<pre><code>git clone https://github.com/justin2004/mssql_server_tiny.git\ncd mssql_server_tiny</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37061\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-173735.jpg\" alt=\"\" width=\"1024\" height=\"769\" /></p>\n<p>I changed the FROM to build from the 2019 RHEL image and I preferred to use /etc/ld.so.preload rather than overriding the CMD command with LD_LIBRARY:</p>\n<pre><code>\nFROM oraclelinux:7-slim AS build0\nWORKDIR /root\nRUN yum update -y &amp;&amp; yum install -y binutils gcc\nADD wrapper.c /root/\nRUN gcc -shared  -ldl -fPIC -o wrapper.so wrapper.c\nFROM mcr.microsoft.com/mssql/rhel/server:2019-latest\nCOPY --from=build0 /root/wrapper.so /root/\nADD wrapper.c /root/\nUSER root\nRUN echo \"/root/wrapper.so\" &gt; /etc/ld.so.preload\nUSER mssql\n</code></pre>\n<p>I didn&#8217;t change the wrapper for the sysinfo function:</p>\n<pre><code>#define _GNU_SOURCE\n#include \n#include \n#include\nint sysinfo(struct sysinfo *info){\n    // clear it\n    //dlerror();\n    void *pt=NULL;\n    typedef int (*real_sysinfo)(struct sysinfo *info);\n    // we need the real sysinfo function address\n    pt = dlsym(RTLD_NEXT,\"sysinfo\");\n    //printf(\"pt: %x\\n\", *(char *)pt);\n    // call the real sysinfo system call\n    int real_return_val=((real_sysinfo)pt)(info);\n    // but then modify its returned totalram field if necessary\n    // because sqlserver needs to believe it has \"2000 megabytes\"\n    // physical memory\n    if( info-&gt;totalram totalram = 1000l * 1000l * 1000l * 2l ;\n    }\n    return real_return_val;\n}\n</code></pre>\n<p>I build the image from there:</p>\n<pre><code>docker build -t mssql .</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37070\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-175629.jpg\" alt=\"\" width=\"1024\" height=\"523\" /><br />\nI run it:</p>\n<pre><code>docker run -d \\\n -e \"ACCEPT_EULA=Y\" \\\n -e 'MSSQL_PID=Express' \\\n -p 1433:1433 \\\n -e 'SA_PASSWORD=**P455w0rd**' \\\n --name mssql \\\n mssql</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37069\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-180121-scaled.jpg\" alt=\"\" width=\"1024\" height=\"558\" /></p>\n<p>I wait until it is ready:</p>\n<pre><code>until docker logs mssql  | grep -C10 \"Recovery is complete.\" ; do sleep 1 ; done</code></pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37068\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-180219.jpg\" alt=\"\" width=\"1024\" height=\"236\" /></p>\n<p>All is ok and I connect and check the version:</p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37067\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/Annotation-2020-02-08-180605-scaled.jpg\" alt=\"\" width=\"1024\" height=\"493\" /></p>\n<p>Well&#8230; as you can see my first attempt failed. I am running with very low memory here, and then many memory allocation problems can be expected. If you look at the logs after a while, many automatic system tasks fail. But that&#8217;s sufficient for a minimal lab and you can tweak some Linux and SQL Server parameters if you need it. Comments are welcome here for feedback and ideas&#8230;</p>\n<p>The port 1433 is exposed here locally and it can be tunneled through ssh. This is a free lab environment always accessible from everywhere to do small tests in MS SQL, running on the Oracle free tier. Here is how I connect with <a href=\"https://dbeaver.io/download/\" target=\"_blank\" rel=\"noopener noreferrer\">DBeaver</a> from my laptop, just mentioning the public IP address, private ssh key and connection information:</p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-37088\" src=\"https://www.dbi-services.com/blog/wp-content/uploads/sites/2/2022/04/oraclefreetierforsqlserver002-1.png\" alt=\"\" width=\"1024\" height=\"683\" /></p>\n",
    "protected": false
  }
}
