{"id":1507,"date":"2024-09-04T01:46:23","date_gmt":"2024-09-04T01:46:23","guid":{"rendered":"https:\/\/craftcookcode.com\/?p=1507"},"modified":"2024-09-04T04:58:00","modified_gmt":"2024-09-04T04:58:00","slug":"qlik-replicate-youre-trapped-in-a-docker-container-now","status":"publish","type":"post","link":"https:\/\/craftcookcode.com\/?p=1507","title":{"rendered":"Qlik Replicate: You&#8217;re trapped in a Docker container now!"},"content":{"rendered":"\n<p>In Qlik Replicate we tasks unable to resume when we have nasty server failures (for instant the CrowdStrike outage in July 2024).<\/p>\n\n\n\n<p>This only happens in tasks that are impacted are a RDBMS to a cloud storage system like AWS S3 or GCS.&nbsp;<\/p>\n\n\n\n<p>In the task log the error message takes the form of:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; quick-code: false; notranslate\" title=\"\">\n00002396: 2022-08-26T15:21:14 &#x5B;AT_GLOBAL ]E: Json doesn&#039;t start with &#039;{&#039; &#x5B;1003001] (at_cjson.c:1773)\n00002396: 2022-08-26T15:21:14 &#x5B;AT_GLOBAL ]E: Cannot parse json: &#x5B;1000251] (at_protobuf.c:1420)\n<\/pre><\/div>\n\n\n<p>This error gives us problems; I can\u2019t resume the task as the error re-appears.&nbsp; I can\u2019t even start it from the stream position and must rely on restarting the QR task from a timestamp, which is extremely dangerous with the chance of missing out on data for that split of a second.<\/p>\n\n\n\n<p>I suspect the problem is that the \u201cstaging\u201d file on the QR server gets corrupted mid write when the server fails and when resume; QR can\u2019t parse it.<\/p>\n\n\n\n<p>But trying to recreate the problem in a safe environment to diagnose it is tricky.&nbsp; Our DTL environment doesn\u2019t create enough traffic to trigger the issue.&nbsp; Also, I don\u2019t want to be abruptly turning off our DTL QR servers and interrupting other people\u2019s testing.&nbsp; As for trying to recreate the problem in production \u2013 the pain of all the red tape is not worth the effort.<\/p>\n\n\n\n<p>I needed a safer space to work in.&nbsp; A space when I can pump through large volumes of data through QR and kick the QR service around trying to provoke the error.&nbsp; Armed with my little Linux VM \u2013 docker containers was the answer.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">CentOS? Why CentOS?<\/h2>\n\n\n\n<p>My goal was to build a Docker container with Qlik Replicate and Postgres drivers so I can use it on my Linux VM.<\/p>\n\n\n\n<p>Under Support articles, Qlik has a guide on how to run <a href=\"https:\/\/community.qlik.com\/t5\/Official-Support-Articles\/How-to-install-Qlik-Replicate-on-a-docker-image\/tac-p\/2477910\" target=\"_blank\" rel=\"noopener\" title=\"\">Qlik Replicate in a Docker container<\/a>.<\/p>\n\n\n\n<p>Following the instructions I ran into some initial problems.&nbsp; The first major problem was using the Cent OS docker image.&nbsp; The issue was that I must use the packages in my company\u2019s artifactory and not external packages.&nbsp; Although the company had CentOS; there was no other packages available to update and install.&nbsp; Since my VM cannot reach http:\/\/vault.centos.org; the CentOS image was a lame duck.<\/p>\n\n\n\n<p>With CentOS off the cards, I had to use Redhat image that my company provided.&nbsp; With Redhat \u2013 the artifactory had all the packages that I needed.<\/p>\n\n\n\n<p>The second problem was that I was wanting to use the 2023.11 image to match our environment.\u00a0 With 2023.11 there are some extra steps needed in the docker file compared to 2024.05.\u00a0 The differences is notated on Qlik&#8217;s support article.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Dockerfile<\/h2>\n\n\n\n<p>Here is the Dockerfile <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: yaml; title: ; quick-code: false; notranslate\" title=\"\">\nFROM my.companys.repo\/redhat\/ubi9\n\n\nENV QLIK_REPLICATE_BASE_DIR=\/opt\/attunity\/replicate\/\nENV ReplicateDataFolder=\/replicate\/data\nENV ReplicateAdminPassword=AB1gL0ngPa33w0rd\nENV ReplicateRestPort=3552\nENV LicenseFile=\/tmp\/replicate_license_exp2025-06-29_ser60038556.txt\n\n# Copy across installation packages and licenses\nADD postgresql*.rpm \/tmp\/\nADD areplicate-*.rpm \/tmp\/\nADD systemctl \/usr\/sbin\nADD replicate_license_exp2025-06-29_ser60038556.txt \/tmp\/\n\n# Update packages\nRUN dnf -y update\nRUN dnf makecache\n\n# To get ps command\nRUN dnf -y install procps-ng\nRUN dnf -y install unixODBC unzip\nRUN dnf -y install libicu.x86_64\nRUN rm -f \/etc\/odbcinst.ini\n\n# Installing posgres packages\nRUN rpm -ivh \/tmp\/postgresql13-libs-13.9-1PGDG.rhel9.x86_64.rpm\nRUN rpm -ivh \/tmp\/postgresql13-odbc-13.02.0000-2PGDG.rhel9.x86_64.rpm\nRUN rpm -ivh \/tmp\/postgresql13-13.9-1PGDG.rhel9.x86_64.rpm\n\nADD odbcinst.ini \/etc\/\n\n# Installing Qlik Replicate\nRUN systemd=no yum -y install \/tmp\/areplicate-2023.11.0-468.x86_64.rpm\nRUN yum clean all\nRUN rm -f \/tmp\/areplicate-*.rpm\n\nRUN export LD_LIBRARY_PATH=\/opt\/attunity\/replicate\/lib:\\$LD_LIBRARY_PATH\nRUN echo &quot;export LD_LIBRARY_PATH=\/usr\/pgsql-13\/lib:\\$LD_LIBRARY_PATH&quot; &gt;&gt; \/opt\/attunity\/replicate\/bin\/site_arep_login.sh\n\nADD start_replicate.sh \/opt\/attunity\/replicate\/bin\/start_replicate.sh\nRUN chmod 775 \/opt\/attunity\/replicate\/bin\/start_replicate.sh\nRUN chown attunity:attunity \/opt\/attunity\/replicate\/bin\/start_replicate.sh\nRUN source $QLIK_REPLICATE_BASE_DIR\/bin\/arep_login.sh &gt;&gt;~attunity\/.bash_profile\nENTRYPOINT \/opt\/attunity\/replicate\/bin\/start_replicate.sh ${ReplicateDataFolder} ${ReplicateAdminPassword} ${ReplicateRestPort} ${LicenseFile} ; tail -f \/dev\/null\n<\/pre><\/div>\n\n\n<p>The postgres packages can be obtained from https:\/\/download.postgresql.org\/pub\/repos\/yum\/13\/redhat\/rhel-9-x86_64\/<\/p>\n\n\n\n<p>Th file odbcinst.ini content is:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; quick-code: false; notranslate\" title=\"\">\n&#x5B;PostgreSQL]\nDescription = ODBC for PostgreSQL\nDriver      = \/usr\/lib\/psqlodbcw.so\nSetup       = \/usr\/lib\/libodbcpsqlS.so\nDriver64    = \/usr\/pgsql-13\/lib\/psqlodbcw.so\nSetup64     = \/usr\/lib64\/libodbcpsqlS.so\nFileUsage   = 1\n\n<\/pre><\/div>\n\n\n<p>The systemctl file is:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; quick-code: false; notranslate\" title=\"\">\n# Run LS command - remove this line \nls\n<\/pre><\/div>\n\n\n<p>And of course you need the rpm for Qlik replicate and your license file.<\/p>\n\n\n\n<p>Once the Dockerfile and files are collated in a directory; build the container with:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; quick-code: false; notranslate\" title=\"\">\ndocker build --no-cache -t ccc\/replicate:2023.11 .\n<\/pre><\/div>\n\n\n<p>If all goes well &#8211; a Docker contain will be built and ready to be used.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Docker Compose<\/h2>\n\n\n\n<p>To make running the docker images easier; create a docker compose file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: yaml; title: ; quick-code: false; notranslate\" title=\"\">\nversion: &#039;3.3&#039;\n\nservices:\n  replicate:\n    image: docker.io\/ccc\/replicate:2023.11\n    container_name: replicate_2023_11\n    ports: \n      - &quot;3552:3552&quot;\n\n    environment:\n      - ReplicateRestPort=3552\n      - TZ=Australia\/Melbourne\n\n    volumes:\n      - \/dockermount\/data\/replicate\/data:\/replicate\/data\n\n    extra_hosts:\n      - host.docker.internal:host-gateway\n\nvolumes:\n  replicate:\n\n<\/pre><\/div>\n\n\n<p>Save the docker-compose.yml in a directory and from the directory start the container with the command:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker-compose up -d\n<\/pre><\/div>\n\n\n<p>If everything is working &#8211; run the docker ps command to verify everything is working:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker ps\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"64\" src=\"https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_01-1024x64.png\" alt=\"\" class=\"wp-image-1516\" srcset=\"https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_01-1024x64.png 1024w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_01-300x19.png 300w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_01-768x48.png 768w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_01.png 1259w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>So far looking good.  Further conformation can be had by connecting into the container and observe the QR processes running:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker exec -it qr_container_id bash\nps -aux\n<\/pre><\/div>\n\n\n<p>There should be two main processes; plus a process for each individual QR tasks running:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"132\" src=\"https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_02-1024x132.png\" alt=\"\" class=\"wp-image-1518\" srcset=\"https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_02-1024x132.png 1024w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_02-300x39.png 300w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_02-768x99.png 768w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_02.png 1276w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>With everything confirmed &#8211; QR console can be accessed from a browser.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nhttps:\/\/127.0.0.1:3552\/attunityreplicate\/\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"393\" src=\"https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_03-1024x393.png\" alt=\"\" class=\"wp-image-1522\" srcset=\"https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_03-1024x393.png 1024w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_03-300x115.png 300w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_03-768x295.png 768w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_03-1536x589.png 1536w, https:\/\/craftcookcode.com\/wp-content\/uploads\/2024\/09\/code_qr_docker_03.png 1914w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>In Qlik Replicate we tasks unable to resume when we have nasty server failures (for instant the CrowdStrike outage in July 2024). This only happens in&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":1429,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[68,64,16],"tags":[65,56,36],"class_list":["post-1507","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-docker","category-postgres","category-qlik-replicate","tag-docker","tag-postgres","tag-qlikreplicate"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/craftcookcode.com\/index.php?rest_route=\/wp\/v2\/posts\/1507","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/craftcookcode.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/craftcookcode.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/craftcookcode.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/craftcookcode.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1507"}],"version-history":[{"count":13,"href":"https:\/\/craftcookcode.com\/index.php?rest_route=\/wp\/v2\/posts\/1507\/revisions"}],"predecessor-version":[{"id":1523,"href":"https:\/\/craftcookcode.com\/index.php?rest_route=\/wp\/v2\/posts\/1507\/revisions\/1523"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/craftcookcode.com\/index.php?rest_route=\/wp\/v2\/media\/1429"}],"wp:attachment":[{"href":"https:\/\/craftcookcode.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1507"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/craftcookcode.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1507"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/craftcookcode.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1507"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}