<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>docker &amp;mdash; Journal from Kotnik</title>
    <link>https://nikola.kotur.org/tag:docker</link>
    <description>Nikola&#39;s thoughts and discoveries</description>
    <pubDate>Mon, 04 May 2026 17:39:51 +0000</pubDate>
    <item>
      <title>Running WriteFreely on Docker with Traefik</title>
      <link>https://nikola.kotur.org/running-writefreely-on-docker-with-traefik</link>
      <description>&lt;![CDATA[Update: Upgrade to WriteFreely 0.13.1 is covered here.&#xA;&#xA;I guess that, by now, it&#39;s tradition to restart my blog on various platforms. Here&#39;s what it took to run this one using writefreely. I work in company that runs apps, so I always experiment with other tools and this time I am running this blog on #Docker using Traefik to route the data around. !--more--&#xA;&#xA;Alright, let&#39;s get on with it. This blog post will not describe every single detail, but just overall steps it took for you to read what you are reading now.&#xA;&#xA;Containers&#xA;&#xA;WriteFreely doesn&#39;t provide ready-made containers one can simply use in own docker-compose.yml so I built one. Luckily they give us functional Dockerfile so I created it:&#xA;&#xA;git clone https://github.com/writeas/writefreely&#xA;cd writefreely/&#xA;git checkout v0.12.0&#xA;docker build -t kotnik/writefreely:0.12.0 .&#xA;docker push kotnik/writefreely:0.12.0&#xA;&#xA;Easy. You can use the image yourself if you want to, this is the latest version as of writing this.&#xA;&#xA;Setup&#xA;&#xA;First time you run it, #WriteFreely needs new keys generated and configuration written. Configuration itself is not complex, you can see here mine. But, in order to generate keys and import config into database you need working environment, and that&#39;s the only non-standard issue here.&#xA;&#xA;You see, WriteFreely&#39;s docker container fails to start since it can&#39;t find those keys, and in order to generate it, you need it running. So, pragmatical as always, I created another image just used for initialization. It&#39;s not the smartest thing you will see today:&#xA;&#xA;docker build -t kotnik/writefreely-init:0.12.0 -&lt;&lt;EOF&#xA;FROM ubuntu&#xA;RUN apt-get update &amp;&amp; apt-get install -y wget &amp;&amp; rm -rf /var/lib/apt/lists/*&#xA;RUN mkdir -p /wf  &amp;&amp; cd /wf&#xA;RUN wget https://github.com/writeas/writefreely/releases/download/v0.12.0/writefreely0.12.0linuxamd64.tar.gz&#xA;RUN tar xzvf writefreely0.12.0linuxamd64.tar.gz &amp;&amp; rm writefreely0.12.0linuxamd64.tar.gz&#xA;CMD [&#34;sleep&#34;, &#34;infinity&#34;]&#xA;EOF&#xA;&#xA;Of course, you can use that one yourself too.&#xA;&#xA;And then we go on.&#xA;&#xA;First run&#xA;&#xA;Docker compose file is as you&#39;d expect:&#xA;&#xA;version: &#34;3&#34;&#xA;&#xA;services:&#xA;  web:&#xA;    image: kotnik/writefreely:0.12.0&#xA;    volumes:&#xA;      &#34;./config.ini:/go/config.ini&#34;&#xA;      web-keys:/go/keys&#xA;    networks:&#xA;      writefreely&#xA;      web&#xA;    restart: unless-stopped&#xA;    labels:&#xA;      &#34;traefik.enable=true&#34;&#xA;      &#34;traefik.http.routers.wf.rule=Host(nikola.kotur.org)&#34;&#xA;      &#34;traefik.http.routers.wf.tls=true&#34;&#xA;      &#34;traefik.http.routers.wf.tls.certresolver=myresolver&#34;    &#xA;      &#34;traefik.http.routers.wf.entrypoints=web, websecure&#34;&#xA;      &#34;traefik.docker.network=web&#34;&#xA;&#xA;  init:&#xA;    image: kotnik/writefreely-init:0.12.0&#xA;    volumes:&#xA;      &#34;./config.ini:/go/config.ini&#34;&#xA;      web-keys:/go/keys&#xA;    networks:&#xA;      writefreely&#xA;    dependson:&#xA;      db&#xA;&#xA;  db:&#xA;    image: &#34;mariadb:latest&#34;&#xA;    volumes:&#xA;      db-data:/var/lib/mysql&#xA;    networks:&#xA;      writefreely&#xA;    environment:&#xA;      MYSQLROOTPASSWORD=silly&#xA;      MYSQLDATABASE=writefreely&#xA;      MYSQLPASSWORD=somepassword&#xA;      MYSQLUSER=someusername&#xA;    restart: unless-stopped&#xA;&#xA;volumes:&#xA;  web-keys:&#xA;  db-data:&#xA;&#xA;networks:&#xA;  writefreely:&#xA;  web:&#xA;    external: true&#xA;&#xA;I am not going to go deep into #Traefik labels, if you spend enough time to actually run it you will have no issues understanding mine configuration here. But, first run is a bit different. We need to run the init container first:&#xA;&#xA;docker-compose up -d init&#xA;&#xA;Wait a bit for the database to be auto-created, it will take about the time to fetch that coffee. Then, attach to the init:&#xA;&#xA;docker exec -it writefreelyinit_1 bash&#xA;&#xA;Run this once inside:&#xA;&#xA;cd /go &amp;&amp; mkdir keys&#xA;/writefreely/writefreely config start&#xA;/writefreely/writefreely keys generate&#xA;&#xA;Congratulations, your instance is configured.&#xA;&#xA;Running&#xA;&#xA;Stop everything:&#xA;&#xA;docker-compose down&#xA;&#xA;Open docker-compose.yml file and remove init container since you will never need it again. Bring your site up:&#xA;&#xA;docker-compose up -d&#xA;&#xA;Open it in browser and start writing!&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><strong>Update</strong>: Upgrade to WriteFreely 0.13.1 is <a href="https://nikola.kotur.org/writefreely-docker-image-upgraded-to-0-13-1">covered here</a>.</p>

<p>I guess that, by now, it&#39;s tradition to restart my blog on various platforms. Here&#39;s what it took to run this one using <a href="https://writefreely.org/">writefreely</a>. I work in company that runs apps, so I always experiment with other tools and this time I am running this blog on <a href="https://nikola.kotur.org/tag:Docker" class="hashtag"><span>#</span><span class="p-category">Docker</span></a> using <a href="https://containo.us/traefik/">Traefik</a> to route the data around. </p>

<p>Alright, let&#39;s get on with it. This blog post will not describe every single detail, but just overall steps it took for you to read what you are reading now.</p>

<h2 id="containers">Containers</h2>

<p>WriteFreely doesn&#39;t provide ready-made containers one can simply use in own <code>docker-compose.yml</code> so I built one. Luckily they give us functional <code>Dockerfile</code> so I created it:</p>

<pre><code class="language-bash">git clone https://github.com/writeas/writefreely
cd writefreely/
git checkout v0.12.0
docker build -t kotnik/writefreely:0.12.0 .
docker push kotnik/writefreely:0.12.0
</code></pre>

<p>Easy. You can use <a href="https://hub.docker.com/repository/docker/kotnik/writefreely">the image</a> yourself if you want to, this is the latest version as of writing this.</p>

<h2 id="setup">Setup</h2>

<p>First time you run it, <a href="https://nikola.kotur.org/tag:WriteFreely" class="hashtag"><span>#</span><span class="p-category">WriteFreely</span></a> needs new keys generated and configuration written. Configuration itself is not complex, you can <a href="https://git.kotur.org/kotnik/writefreely-resources/src/b67b23596929fa59fc5b9810b7a79fbb306b3654/config.ini">see here mine</a>. But, in order to generate keys and import config into database you need working environment, and that&#39;s the only non-standard issue here.</p>

<p>You see, WriteFreely&#39;s docker container fails to start since it can&#39;t find those keys, and in order to generate it, you need it running. So, pragmatical as always, I created another image just used for initialization. It&#39;s not the smartest thing you will see today:</p>

<pre><code class="language-bash">docker build -t kotnik/writefreely-init:0.12.0 -&lt;&lt;EOF
FROM ubuntu
RUN apt-get update &amp;&amp; apt-get install -y wget &amp;&amp; rm -rf /var/lib/apt/lists/*
RUN mkdir -p /wf  &amp;&amp; cd /wf
RUN wget https://github.com/writeas/writefreely/releases/download/v0.12.0/writefreely_0.12.0_linux_amd64.tar.gz
RUN tar xzvf writefreely_0.12.0_linux_amd64.tar.gz &amp;&amp; rm writefreely_0.12.0_linux_amd64.tar.gz
CMD [&#34;sleep&#34;, &#34;infinity&#34;]
EOF
</code></pre>

<p>Of course, you can use that <a href="https://hub.docker.com/repository/docker/kotnik/writefreely-init">one yourself</a> too.</p>

<p>And then we go on.</p>

<h2 id="first-run">First run</h2>

<p>Docker compose file is as you&#39;d expect:</p>

<pre><code class="language-yaml">version: &#34;3&#34;

services:
  web:
    image: kotnik/writefreely:0.12.0
    volumes:
      - &#34;./config.ini:/go/config.ini&#34;
      - web-keys:/go/keys
    networks:
      - writefreely
      - web
    restart: unless-stopped
    labels:
      - &#34;traefik.enable=true&#34;
      - &#34;traefik.http.routers.wf.rule=Host(`nikola.kotur.org`)&#34;
      - &#34;traefik.http.routers.wf.tls=true&#34;
      - &#34;traefik.http.routers.wf.tls.certresolver=myresolver&#34;    
      - &#34;traefik.http.routers.wf.entrypoints=web, websecure&#34;
      - &#34;traefik.docker.network=web&#34;

  init:
    image: kotnik/writefreely-init:0.12.0
    volumes:
      - &#34;./config.ini:/go/config.ini&#34;
      - web-keys:/go/keys
    networks:
      - writefreely
    depends_on:
      - db

  db:
    image: &#34;mariadb:latest&#34;
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - writefreely
    environment:
      - MYSQL_ROOT_PASSWORD=silly
      - MYSQL_DATABASE=writefreely
      - MYSQL_PASSWORD=somepassword
      - MYSQL_USER=someusername
    restart: unless-stopped

volumes:
  web-keys:
  db-data:

networks:
  writefreely:
  web:
    external: true
</code></pre>

<p>I am not going to go deep into <a href="https://nikola.kotur.org/tag:Traefik" class="hashtag"><span>#</span><span class="p-category">Traefik</span></a> labels, if you spend enough time to actually run it you will have no issues understanding mine configuration here. But, first run is a bit different. We need to run the <code>init</code> container first:</p>

<pre><code class="language-bash">docker-compose up -d init
</code></pre>

<p>Wait a bit for the database to be auto-created, it will take about the time to fetch that coffee. Then, attach to the <code>init</code>:</p>

<pre><code class="language-bash">docker exec -it writefreely_init_1 bash
</code></pre>

<p>Run this once inside:</p>

<pre><code class="language-bash">cd /go &amp;&amp; mkdir keys
/writefreely/writefreely config start
/writefreely/writefreely keys generate
</code></pre>

<p>Congratulations, your instance is configured.</p>

<h2 id="running">Running</h2>

<p>Stop everything:</p>

<pre><code class="language-bash">docker-compose down
</code></pre>

<p>Open <code>docker-compose.yml</code> file and remove <code>init</code> container since you will never need it again. Bring your site up:</p>

<pre><code class="language-bash">docker-compose up -d
</code></pre>

<p>Open it in browser and start writing!</p>
]]></content:encoded>
      <guid>https://nikola.kotur.org/running-writefreely-on-docker-with-traefik</guid>
      <pubDate>Thu, 06 Aug 2020 15:34:14 +0000</pubDate>
    </item>
  </channel>
</rss>