<p>Good morning,</p>

<p>I'm very new to Docker and Kubernetes, and I do not really know where to start looking for help. I created a database container with Docker and I want manage it and scale with Kubernetes. I started  installing minikube in my machine, and tried to create a Deployment first and then a StatefulSet for a database container. But I have a problem with the StatefulSet when creating a Pod with a database (mariadb or mysql). When I use a Deployment the Pods are loaded and work fine. However, the same Pods are not working when using them in a StatefulSet, returning errors asking for the MYSQL constants. This is the Deployment, and I use the command <code>kubectl create -f deployment.yaml</code>:</p>

<pre><code>apiVersion: apps/v1beta1
kind: Deployment
metadata:
 name: mydb-deployment
spec:
 template:
  metadata:
   labels: 
    name: mydb-pod
  spec:
   containers:
    - name: mydb
      image: ignasiet/aravomysql
      ports:
       - containerPort: 3306
</code></pre>

<p>And when listing the deployments: <code>kubectl get Deployments</code>:</p>

<pre><code>NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
mydb-deployment    1         1         1            1           2m
</code></pre>

<p>And the pods: <code>kubectl get pods</code>:</p>

<pre><code>NAME                                READY   STATUS    RESTARTS   AGE
mydb-deployment-59c867c49d-4rslh    1/1     Running   0          50s
</code></pre>

<p>But since I want to create a persistent database, I try to create a statefulSet object with the same container, and a persistent volume.
Thus, when creating the following StatefulSet with <code>kubectl create -f statefulset.yaml</code>:</p>

<pre><code>apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
 name: statefulset-mydb
spec:
 serviceName: mydb-pod
 template:
  metadata:
   labels: 
    name: mydb-pod
  spec:
   containers:
    - name: aravo-database
      image: ignasiet/aravomysql
      ports:
       - containerPort: 3306
      volumeMounts:
       - name: volume-mydb
         mountPath: /var/lib/mysql
   volumes:
    - name: volume-mydb
      persistentVolumeClaim: 
       claimName: config-mydb
</code></pre>

<p>With the service <code>kubectl create -f service-db.yaml</code>: </p>

<pre><code>apiVersion: v1
kind: Service
metadata:
 name: mydb
spec:
 type: ClusterIP
 ports:
  - port: 3306
 selector:
  name: mydb-pod
</code></pre>

<p>And the permission file <code>kubectl create -f permissions.yaml</code>:</p>

<pre><code>apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: config-mydb
spec:
 accessModes: 
  - ReadWriteOnce
 resources:
  requests:
   storage: 3Gi
</code></pre>

<p>The pods do not work. They give an error:</p>

<pre><code>NAME                    READY   STATUS             RESTARTS   AGE
statefulset-mydb-0      0/1     CrashLoopBackOff   1          37s
</code></pre>

<p>And when analyzing the logs kubectl logs statefulset-mydb-0:</p>

<pre><code>`error: database is uninitialized and password option is not specified
You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD`
</code></pre>

<p>How it is possible that it does ask for these variables when the container has already an initialization script and works perfectly? And why it asks only when launching as statefulSet, and not when launching the Deployment?</p>

<p>Thanks in advance.</p>

<p>I pulled your image <code>ignasiet/aravomysql</code> to try to figure out what went wrong. As it turns out, your image already has an initialized MySQL data directory at <code>/var/lib/mysql</code>:</p>

<pre><code>$ docker run -it --rm --entrypoint=sh ignasiet/aravomysql:latest
# ls -al /var/lib/mysql 
total 110616
drwxr-xr-x 1 mysql mysql      240 Nov  7 13:19 .
drwxr-xr-x 1 root  root        52 Oct 29 18:19 ..
-rw-rw---- 1 root  root     16384 Oct 29 18:18 aria_log.00000001
-rw-rw---- 1 root  root        52 Oct 29 18:18 aria_log_control
-rw-rw---- 1 root  root      1014 Oct 29 18:18 ib_buffer_pool
-rw-rw---- 1 root  root  50331648 Oct 29 18:18 ib_logfile0
-rw-rw---- 1 root  root  50331648 Oct 29 18:18 ib_logfile1
-rw-rw---- 1 root  root  12582912 Oct 29 18:18 ibdata1
-rw-rw---- 1 root  root         0 Oct 29 18:18 multi-master.info
drwx------ 1 root  root      2696 Nov  7 13:19 mysql
drwx------ 1 root  root        12 Nov  7 13:19 performance_schema
drwx------ 1 root  root        48 Nov  7 13:19 yypy
</code></pre>

<p>However, when mounting a <code>PersistentVolume</code> or just a simple Docker volume to <code>/var/lib/mysql</code>, it's initially empty and therefore the script thinks your database is uninitialized. You can reproduce this issue with:</p>

<pre><code>$ docker run -it --rm --mount type=tmpfs,destination=/var/lib/mysql ignasiet/aravomysql:latest
error: database is uninitialized and password option is not specified 
  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD
</code></pre>

<p>If you have a bunch of scripts you need to run to initialize the database, you have two options:</p>

<ol>
<li>Create a Dockerfile based on the <code>mysql</code> Dockerfile, and add shell scripts or SQL scripts to <code>/docker-entrypoint-initdb.d</code>. More details available <a href="https://docs.docker.com/samples/library/mysql/#docker-secrets" rel="nofollow noreferrer">here</a> under "Initializing a fresh instance".</li>
<li>Use the <code>initContainers</code> property in the PodTemplateSpec, something like:</li>
</ol>

<pre><code>apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: statefulset-mydb
spec:
  serviceName: mydb-pod
  template:
  metadata:
    labels: 
    name: mydb-pod
  spec:
    containers:
    - name: aravo-database
      image: ignasiet/aravomysql
      ports:
        - containerPort: 3306
      volumeMounts:
        - name: volume-mydb
          mountPath: /var/lib/mysql
    initContainers:
    - name: aravo-database-init
      command:
        - /script/to/initialize/database
      image: ignasiet/aravomysql
      volumeMounts:
        - name: volume-mydb
          mountPath: /var/lib/mysql
    volumes:
    - name: volume-mydb
      persistentVolumeClaim: 
        claimName: config-mydb
</code></pre>
