{"id":12835,"date":"2019-09-29T16:54:15","date_gmt":"2019-09-29T14:54:15","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/"},"modified":"2023-07-13T15:46:47","modified_gmt":"2023-07-13T13:46:47","slug":"using-non-root-sql-server-containers-on-docker-and-k8s","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/","title":{"rendered":"Using non-root SQL Server containers on Docker and K8s"},"content":{"rendered":"<p><span style=\"font-family: Calibri;\"><span lang=\"EN-US\"><span style=\"color: #000000;\">This is something that I waited for a while, in fact since SQL Server 2017 \u2026 and the <\/span><\/span><a href=\"https:\/\/techcommunity.microsoft.com\/t5\/SQL-Server\/Non-Root-SQL-Server-2019-Containers\/ba-p\/859644\" target=\"_blank\" rel=\"noopener noreferrer\"><span lang=\"EN-US\">news<\/span><\/a><span lang=\"EN-US\"><span style=\"color: #000000;\"> came out on Wednesday 09<sup>th<\/sup> September 2019. Running Non-Root SQL Server Containers is now possible either on the next version of SQL Server (2019) and it has been backported on SQL Server 2017 as well. Non-root SQL Server containers will likely be part of hidden gem of SQL Server new features, but this is definitely a good news for me because it will facilitate the transition of SQL Server containers on production from a security standpoint. <\/span><\/span><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-34578 size-full\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg\" alt=\"\" width=\"900\" height=\"300\" \/><\/p>\n<p><span lang=\"EN-US\">At this stage, no need to precise why it is not a best practice to run SQL Server containers or more generally speaking applications with root privileges within a container. For further information, I invite you to take a look at the different threats implied by a such configuration with your google-fu.\u00a0<\/span><\/p>\n<p><span style=\"font-family: Calibri;\"><span lang=\"EN-US\"><span style=\"color: #000000;\">Let\u2019s start with docker environments. First,<b> <\/b>Microsoft provides a <\/span><\/span><a href=\"https:\/\/raw.githubusercontent.com\/microsoft\/mssql-docker\/master\/linux\/preview\/examples\/mssql-server-linux-non-root\/Dockerfile-2019\" target=\"_blank\" rel=\"noopener noreferrer\"><span lang=\"EN-US\">Docker file<\/span><\/a><span lang=\"EN-US\"><span style=\"color: #000000;\"> to build an image either for SQL Server 2017 and SQL Server 2019. We may notice the Docker file is already based on a SQL Server docker image and performs some extra configuration for non-root privilege capabilities. I put here the interesting part:<\/span><b><\/b><\/span><\/span><\/p>\n<pre class=\"brush: shell; gutter: true; first-line: 1\"># Exmple of creating a SQL Server 2019 container image that will run as a user 'mssql' instead of root\n# This is example is based on the official image from Microsoft and effectively changes the user that SQL Server runs as\n# and allows for dumps to generate as a non-root user\n\n\nFROM mcr.microsoft.com\/mssql\/server:2019-latest\n\n# Create non-root user and update permissions\n#\nRUN useradd -M -s \/bin\/bash -u 10001 -g 0 mssql\nRUN mkdir -p -m 770 \/var\/opt\/mssql &amp;&amp; chgrp -R 0 \/var\/opt\/mssql\n\n# Grant sql the permissions to connect to ports &lt;1024 as a non-root user\n#\nRUN setcap 'cap_net_bind_service+ep' \/opt\/mssql\/bin\/sqlservr\n\n# Allow dumps from the non-root process\n# \nRUN setcap 'cap_sys_ptrace+ep' \/opt\/mssql\/bin\/paldumper\nRUN setcap 'cap_sys_ptrace+ep' \/usr\/bin\/gdb\n\n# Add an ldconfig file because setcap causes the os to remove LD_LIBRARY_PATH\n# and other env variables that control dynamic linking\n#\nRUN mkdir -p \/etc\/ld.so.conf.d &amp;&amp; touch \/etc\/ld.so.conf.d\/mssql.conf\nRUN echo -e \"# mssql libs\\n\/opt\/mssql\/lib\" &gt;&gt; \/etc\/ld.so.conf.d\/mssql.conf\nRUN ldconfig\n\nUSER mssql\nCMD [\"\/opt\/mssql\/bin\/sqlservr\"]<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">Note the different sections where the mssql user is created and is used when running the image. So, the new image specification implies running the sqlservr process using this mssql user as shown below:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ docker exec -ti sql19 top<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-34579 size-full\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-1-docker-mssql-user-e1569774360201.jpg\" alt=\"\" width=\"900\" height=\"120\" \/><\/p>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">The user process is well identified by its name because it is already defined in the \/etc\/password file within the container namespace:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ docker exec -ti sql19 cat \/etc\/passwd | grep mssql\nmssql:x:10001:0::\/home\/mssql:\/bin\/bash<\/pre>\n<p><span lang=\"EN-US\"><span style=\"font-family: Calibri;\"><span style=\"color: #000000;\">Let\u2019s go ahead and let\u2019s talk about persisting SQL Server database files on an external storage. In this case, we need to refer to the <\/span><a href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/linux\/sql-server-linux-configure-docker?view=sql-server-2017#buildnonrootcontainer\" target=\"_blank\" rel=\"noopener noreferrer\">Microsoft documentation<\/a><\/span><span style=\"color: #000000; font-family: Calibri;\"> to configure volumes and underlying storage permissions regarding the scenario we will have to deal with.<\/span><\/span><\/p>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">If you don\u2019t specify any user (and group) when spinning up the container, the sqlservr process will run with the identity of the mssql user created inside the container and as part of the root group. The underlying host filesystem must be configured accordingly, either a user with same UID = 10001 or the root group GUID = 0). Otherwise chances are you will experience permission issues with the following error message:<\/span><\/span><\/p>\n<pre class=\"brush: shell; gutter: true; first-line: 1\">SQL Server 2019 will run as non-root by default.\nThis container is running as user mssql.\nTo learn more visit https:\/\/go.microsoft.com\/fwlink\/?linkid=2099216.\n\/opt\/mssql\/bin\/sqlservr: Error: Directory [\/var\/opt\/mssql\/system\/] could not be created.  Errno [13]<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">If you want to run the container as part of a custom user and group created on your own, you must be aware of the different database file placement scenarios. The first one consists in using the default configuration with all the SQL Server logs, data and transaction log files in \/var\/opt\/mssql path. In this case, your custom user UID and GUID can be part of the security context of the hierarchy folder on the host as follows:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ ls -l | grep sqlserver\ndrwxrwx---. 6 mssql mssql 59 Sep 27 19:08 sqlserver\n\n$ id mssql\nuid=1100(mssql) gid=1100(mssql) groups=1100(mssql),100(users)<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">The docker command below specifies the UID and GUID of my custom user through the -u parameter:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">docker run -d \\\n --name sql19 \\\n -u $(id -u mssql):$(id -g mssql) \\\n -e \"MSSQL_PID=Developer\" \\\n -e \"ACCEPT_EULA=Y\" \\\n -e \"SA_PASSWORD=Password1\" \\\n -e \"MSSQL_AGENT_ENABLED=True\" \\\n -e \"MSSQL_LCID=1033\" \\\n -e \"MSSQL_MEMORY_LIMIT_MB=2048\" \\\n -v \"\/u00\/sqlserver:\/var\/opt\/mssql\" \\\n -p 1451:1433 -d 2019-latest-non-root<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">Note the username is missing and replaced by the UID of the mssql user created on my own. <\/span><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-34581 size-full\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-2-docker-mssql-custom-user-e1569774588227.jpg\" alt=\"\" width=\"900\" height=\"112\" \/><\/p>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">This is a normal behavior because my user is not known within the container namespace. There is no record from my user with UID = 1001. The system only knows the mssql user with UID = 10001 as shown below:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">I have no name!@e698c3db2180:\/$ whoami\nwhoami: cannot find name for user ID 1100\n\n$ cat \/etc\/passwd | grep mssql | cut -d\":\" -f 1,3\nmssql:10001<\/pre>\n<p><span style=\"font-family: Calibri;\"><span lang=\"EN-US\"><span style=\"color: #000000;\">For a sake of curiosity, we may wonder how SQL Server makes the choice of using the correct user for the sqlservr process. Indeed, I created two users with the same name but with different UIDs and I think that after some investigations, taking a look at the <\/span><\/span><a href=\"https:\/\/github.com\/microsoft\/mssql-docker\/blob\/master\/linux\/preview\/CentOS\/uid_entrypoint\" target=\"_blank\" rel=\"noopener noreferrer\"><span lang=\"EN-US\">uid_entry point<\/span><\/a><span lang=\"EN-US\"><span style=\"color: #000000;\"> definition in the microsoft\/mssql-docker github project could help understanding this behavior:<\/span><\/span><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-34583 size-full\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-3-docker-uid_entrypoint-e1569774804657.jpg\" alt=\"\" width=\"900\" height=\"370\" \/><\/p>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">If we don\u2019t specify the UID \/ GUID during the container\u2019s creation, the whoami command will fail and the mssql user\u2019s UID defined in the Dockerfile (cf. USER mssql) will be chosen.<\/span><\/span><\/p>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">\u00a0<\/span><\/span><span style=\"font-family: Calibri;\"><span lang=\"EN-US\"><span style=\"color: #000000;\">The second scenario consists in introducing some SQL Server best practices in terms of database file placement. In a previous <\/span><\/span><a href=\"https:\/\/www.dbi-services.com\/blog\/sql-server-on-linux-and-experimental-flexible-architecture\/\" target=\"_blank\" rel=\"noopener noreferrer\"><span lang=\"EN-US\">blog post<\/span><\/a><span lang=\"EN-US\"><span style=\"color: #000000;\">, I wrote about a possible implementation based on a flexible architecture for SQL Server on Linux and which may fit with containers. In this case, database files will be stored outside of the \/var\/opt\/mssql default path and in this case, the non-root container has the restriction that it must run as part of the root group as mentioned in the <\/span><\/span><a href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/linux\/sql-server-linux-configure-docker?view=sql-server-2017#buildnonrootcontainer\" target=\"_blank\" rel=\"noopener noreferrer\"><span lang=\"EN-US\">Microsoft documentation<\/span><\/a><span lang=\"EN-US\"><span style=\"color: #000000;\">:<\/span><\/span><\/span><\/p>\n<pre class=\"brush: shell; gutter: true; first-line: 1\">The non-root container has the restriction that it must run as part of the root group unless a volume is mounted to '\/var\/opt\/mssql' that the non-root user can access. The root group doesn\u2019t grant any extra root permissions to the non-root user.<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">Here my implementation of the flexible architecture template with required Linux permissions in my context:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ ls -ld \/u[0-9]*\/sql*2\/\ndrwxrwx---. 2 mssql root    6 Sep 24 22:02 \/u00\/sqlserver2\/\ndrwxrwx---. 2 mssql root 4096 Sep 27 14:20 \/u01\/sqlserverdata2\/\ndrwxrwx---. 2 mssql root   25 Sep 27 14:20 \/u02\/sqlserverlog2\/\ndrwxrwx---. 2 mssql root    6 Sep 24 22:04 \/u03\/sqlservertempdb2\/\ndrwxrwx---. 2 mssql root    6 Sep 27 10:09 \/u98\/sqlserver2\/<\/pre>\n<p>\u2026 with:<\/p>\n<ul>\n<li>\/u00\/sqlserver2 (binaries structure that will contain remaining files in \/var\/opt\/mssql path)<\/li>\n<li>\/u01\/sqlserverdata2 (data files including user, system and tempdb databases)<\/li>\n<li>\/u02\/sqlserverlog2 (transaction log files)<\/li>\n<li>\/u98\/sqlserver2 (database backups)<\/li>\n<\/ul>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">And accordingly, my docker command and parameters to start my SQL Server container that will sit on my flexible architecture:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">docker run -d \\\n --name sql19 \\\n -u $(id -u mssql):0 \\\n -e \"MSSQL_PID=Developer\" \\\n -e \"ACCEPT_EULA=Y\" \\\n -e \"SA_PASSWORD=Password1\" \\\n -e \"MSSQL_AGENT_ENABLED=True\" \\\n -e \"MSSQL_LCID=1033\" \\\n -e \"MSSQL_MEMORY_LIMIT_MB=2048\" \\\n -e \"MSSQL_MASTER_DATA_FILE=\/u01\/sqlserverdata\/master.mdf\" \\\n -e \"MSSQL_MASTER_LOG_FILE=\/u02\/sqlserverlog\/mastlog.ldf\" \\\n -e \"MSSQL_DATA_DIR=\/u01\/sqlserverdata\" \\\n -e \"MSSQL_LOG_DIR=\/u02\/sqlserverlog\" \\\n -e \"MSSQL_BACKUP_DIR=\/u98\/sqlserver\" \\\n -v \"\/u00\/sqlserver2:\/var\/opt\/mssql\" \\\n -v \"\/u01\/sqlserverdata2:\/u01\/sqlserverdata\" \\\n -v \"\/u02\/sqlserverlog2:\/u02\/sqlserverlog\" \\\n -v \"\/u98\/sqlserver2:\/u98\/sqlserver\" \\\n -p 1451:1433 -d 2019-latest-non-root<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">The mssql user created on my own from the host (with UID = 1100) is used by the sqlservr process:<\/span><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-34584 size-full\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-4-docker-mssql-custom-user-2-e1569775183256.jpg\" alt=\"\" width=\"900\" height=\"120\" \/><\/p>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">The system and user database files are placed according to my specification:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">master&gt; create database test;\nCommands completed successfully.\nTime: 0.956s\nmaster&gt; \\n ldd %%\n+--------+----------------+---------------------------------+-----------+\n| DB     | logical_name   | physical_name                   | size_MB   |\n|--------+----------------+---------------------------------+-----------|\n| master | master         | \/u01\/sqlserverdata\/master.mdf   | 71        |\n| master | mastlog        | \/u02\/sqlserverlog\/mastlog.ldf   | 32        |\n| tempdb | tempdev        | \/u01\/sqlserverdata\/tempdb.mdf   | 128       |\n| tempdb | templog        | \/u01\/sqlserverdata\/templog.ldf  | 128       |\n| tempdb | tempdev2       | \/u01\/sqlserverdata\/tempdb2.ndf  | 128       |\n| tempdb | tempdev3       | \/u01\/sqlserverdata\/tempdb3.ndf  | 128       |\n| tempdb | tempdev4       | \/u01\/sqlserverdata\/tempdb4.ndf  | 128       |\n| model  | modeldev       | \/u01\/sqlserverdata\/model.mdf    | 128       |\n| model  | modellog       | \/u01\/sqlserverdata\/modellog.ldf | 128       |\n| msdb   | MSDBData       | \/u01\/sqlserverdata\/MSDBData.mdf | 236       |\n| msdb   | MSDBLog        | \/u01\/sqlserverdata\/MSDBLog.ldf  | 12        |\n| test   | test           | \/u01\/sqlserverdata\/test.mdf     | 128       |\n| test   | test_log       | \/u02\/sqlserverlog\/test_log.ldf  | 128       |\n+--------+----------------+---------------------------------+-----------+<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">I may correlate the above output with corresponding files persisted on underlying storage according to my flexible architecture specification:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ sudo ls -lR \/u[0-9]*\/sqlserver*2\/\n\/u00\/sqlserver2\/:\ntotal 4\ndrwxrwx---. 2 mssql root 4096 Sep 28 17:39 log\ndrwxr-xr-x. 2 mssql root   25 Sep 28 17:39 secrets\n\n\/u00\/sqlserver2\/log:\ntotal 428\n-rw-r-----. 1 mssql root  10855 Sep 28 17:39 errorlog\n-rw-r-----. 1 mssql root  10856 Sep 28 17:37 errorlog.1\n-rw-r-----. 1 mssql root      0 Sep 28 17:37 errorlog.2\n-rw-r-----. 1 mssql root  77824 Sep 28 17:37 HkEngineEventFile_0_132141586653320000.xel\n-rw-r-----. 1 mssql root  77824 Sep 28 17:39 HkEngineEventFile_0_132141587692350000.xel\n-rw-r-----. 1 mssql root   2560 Sep 28 17:39 log_1.trc\n-rw-r-----. 1 mssql root   2560 Sep 28 17:37 log.trc\n-rw-r-----. 1 mssql root   6746 Sep 28 17:37 sqlagent.1\n-rw-r-----. 1 mssql root   6746 Sep 28 17:39 sqlagent.out\n-rw-r-----. 1 mssql root    114 Sep 28 17:39 sqlagentstartup.log\n-rw-r-----. 1 mssql root 106496 Sep 28 17:37 system_health_0_132141586661720000.xel\n-rw-r-----. 1 mssql root 122880 Sep 28 17:41 system_health_0_132141587698940000.xel\n\n\/u00\/sqlserver2\/secrets:\ntotal 4\n-rw-------. 1 mssql root 44 Sep 28 17:39 machine-key\n\n\/u01\/sqlserverdata2\/:\ntotal 105220\n-rw-r-----. 1 mssql root      256 Sep 27 14:20 Entropy.bin\n-rw-r-----. 1 mssql root  4653056 Sep 28 17:39 master.mdf\n-rw-r-----. 1 mssql root  8388608 Sep 28 17:39 modellog.ldf\n-rw-r-----. 1 mssql root  8388608 Sep 28 17:39 model.mdf\n-rw-r-----. 1 mssql root 14024704 Sep 27 14:20 model_msdbdata.mdf\n-rw-r-----. 1 mssql root   524288 Sep 27 14:20 model_msdblog.ldf\n-rw-r-----. 1 mssql root   524288 Sep 27 14:20 model_replicatedmaster.ldf\n-rw-r-----. 1 mssql root  4653056 Sep 27 14:20 model_replicatedmaster.mdf\n-rw-r-----. 1 mssql root 15466496 Sep 28 17:39 msdbdata.mdf\n-rw-r-----. 1 mssql root   786432 Sep 28 17:39 msdblog.ldf\n-rw-r-----. 1 mssql root  8388608 Sep 28 17:39 tempdb2.ndf\n-rw-r-----. 1 mssql root  8388608 Sep 28 17:39 tempdb3.ndf\n-rw-r-----. 1 mssql root  8388608 Sep 28 17:39 tempdb4.ndf\n-rw-r-----. 1 mssql root  8388608 Sep 28 17:39 tempdb.mdf\n-rw-r-----. 1 mssql root  8388608 Sep 28 17:39 templog.ldf\n-rw-r-----. 1 mssql root  8388608 Sep 28 17:39 test.mdf\n\n\/u02\/sqlserverlog2\/:\ntotal 10240\n-rw-r-----. 1 mssql root 2097152 Sep 28 17:39 mastlog.ldf\n-rw-r-----. 1 mssql root 8388608 Sep 28 17:39 test_log.ldf\n\n\/u03\/sqlservertempdb2\/:\ntotal 0\n\n\/u98\/sqlserver2\/:\ntotal 0<\/pre>\n<p><span lang=\"EN-US\"><span style=\"font-family: Calibri;\"><span style=\"color: #000000;\">What next? Because in production your containers will run on the top of orchestrator like Kubernetes, the question is how to implement such privilege restriction in this context? Kubernetes provides <\/span><a href=\"https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/security-context\/\">security context<\/a><\/span><span style=\"color: #000000; font-family: Calibri;\"> at different levels including pod and containers. <\/span><\/span><span lang=\"EN-US\"><span style=\"font-family: Calibri;\"><span style=\"color: #000000;\">In this blog post example, I applied the security context at the container level within the container specification. \u00a0<\/span><\/span><\/span><\/p>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">Let\u2019s set the context. Here the picture of my K8s environment:<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ kubectl get nodes\nNAME                     STATUS   ROLES    AGE   VERSION\nk8m.dbi-services.test    Ready    master   97d   v1.14.1\nk8n1.dbi-services.test   Ready    &lt;none&gt;   97d   v1.14.1\nk8n2.dbi-services.test   Ready    &lt;none&gt;   97d   v1.14.1<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">I used the new local-storage Storage class (available with K8s v.1.14+):<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ kubectl get sc\nNAME            PROVISIONER                    AGE\nlocal-storage   kubernetes.io\/no-provisioner   4d\n\n$ kubectl describe sc local-storage\nName:                  local-storage\nIsDefaultClass:        No\nAnnotations:           &lt;none&gt;\nProvisioner:           kubernetes.io\/no-provisioner\nParameters:            &lt;none&gt;\nAllowVolumeExpansion:  &lt;unset&gt;\nMountOptions:          &lt;none&gt;\nReclaimPolicy:         Delete\nVolumeBindingMode:     WaitForFirstConsumer\nEvents:                &lt;none&gt;<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">I configured a persistent volume based on this local-storage class and that pointing to the \/mnt\/local-storage on my K81n node. The access mode and Retain policy are configured according to meet the best practices for databases.<\/span><\/span><\/p>\n<pre class=\"brush: xml; gutter: true; first-line: 1\">$ cat StoragePV.yaml\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: my-local-pv\nspec:\n  capacity:\n    storage: 5Gi\n  accessModes:\n  - ReadWriteOnce\n  persistentVolumeReclaimPolicy: Retain\n  volumeMode: Filesystem\n  storageClassName: local-storage\n  local:\n    path: \/mnt\/localstorage\n  nodeAffinity:\n    required:\n      nodeSelectorTerms:\n      - matchExpressions:\n        - key: kubernetes.io\/hostname\n          operator: In\n          values:\n          - k8n1.dbi-services.test<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">For a sake of simplicity, I applied the default configuration with all SQL Server related files related stored in \/var\/opt\/mssql. I configured the underlying storage and folder permissions accordingly with my custom mssql user (UID = 10001) and group (GUID = 10001) created on the K8n1 host. Note that the UID matches with that of the mssql user created within the container. <\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ hostname\nk8n1.dbi-services.test\n\n$ id mssql\nuid=10001(mssql) gid=10001(mssql) groups=10001(mssql)\n\n$ ls -ld \/mnt\/localstorage\/\ndrwxrwx--- 6 mssql mssql 59 Sep 26 20:57 \/mnt\/localstorage\/<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">My deployment file is as follows. It includes the security context that specifies a non-root container configuration with my custom user\u2019s UID \/ GUID created previously (runAsUser and runAsGroup parameters):<\/span><\/span><\/p>\n<pre class=\"brush: bash; gutter: true; first-line: 1\">$ cat ReplicaSet.yaml\napiVersion: apps\/v1beta1\nkind: Deployment\nmetadata:\n  name: mssql-deployment-2\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: mssql-2\n    spec:\n      securityContext:\n        runAsUser: 10001\n        runAsGroup: 10001\n      terminationGracePeriodSeconds: 10\n      containers:\n      - name: mssql-2\n        image: trow.kube-public:31000\/2019-latest-non-root\n        ports:\n        - containerPort: 1433\n        env:\n        - name: MSSQL_PID\n          value: \"Developer\"\n        - name: ACCEPT_EULA\n          value: \"Y\"\n        - name: MSSQL_SA_PASSWORD\n          valueFrom:\n            secretKeyRef:\n              name: sql-secrets\n              key: sapassword\n        volumeMounts:\n        - name: mssqldb\n          mountPath: \/var\/opt\/mssql\n      volumes:\n      - name: mssqldb\n        persistentVolumeClaim:\n          claimName: mssql-data-2<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">Obviously, if you don\u2019t meet the correct security permissions on the underlying persistent volume, you will get an error when provisioning the MSSQL pod because the sqlservr process will not get the privileges to create or to access the SQL Server related files as shown below:<\/span><\/span><\/p>\n<pre class=\"brush: shell; gutter: true; first-line: 1\">$ kubectl get pod\nNAME                                 READY   STATUS   RESTARTS   AGE\nmssql-deployment-2-8b4d7f7b7-x4x8w   0\/1     Error    2          30s\n\n$ kubectl logs mssql-deployment-2-8b4d7f7b7-x4x8w\nSQL Server 2019 will run as non-root by default.\nThis container is running as user mssql.\nTo learn more visit https:\/\/go.microsoft.com\/fwlink\/?linkid=2099216.\n\/opt\/mssql\/bin\/sqlservr: Error: Directory [\/var\/opt\/mssql\/system\/] could not be created.  Errno [13]<\/pre>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">If well configured, everything should work as expected and your container should run and interacts correctly with the corresponding persistent volume in the security context defined in your YAML specification:<\/span><\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-34587 size-full\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-5-k8s-mssql-custom-user-e1569775613237.jpg\" alt=\"\" width=\"900\" height=\"135\" \/><\/p>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">All this stuff applies to SQL Server 2017. <\/span><\/span><\/p>\n<p><span lang=\"EN-US\"><span style=\"color: #000000; font-family: Calibri;\">See you!<\/span><\/span><\/p>\n<p><span style=\"float: none; background-color: #ffffff; color: #333333; cursor: text; font-family: Georgia,'Times New Roman','Bitstream Charter',Times,serif; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none;\">By David Barbarin<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is something that I waited for a while, in fact since SQL Server 2017 \u2026 and the news came out on Wednesday 09th September 2019. Running Non-Root SQL Server Containers is now possible either on the next version of SQL Server (2019) and it has been backported on SQL Server 2017 as well. Non-root [&hellip;]<\/p>\n","protected":false},"author":26,"featured_media":12836,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[229,1320,1504,1522,99],"tags":[720,89,1703,1704,1705,1706,25,51],"type_dbi":[],"class_list":["post-12835","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-database-administration-monitoring","category-devops","category-docker","category-kubernetes","category-sql-server","tag-container","tag-kubernetes","tag-peristent-volume","tag-persistent-volume-claim","tag-runasgroup","tag-runasuser","tag-security","tag-sql-server"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Using non-root SQL Server containers on Docker and K8s - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using non-root SQL Server containers on Docker and K8s\" \/>\n<meta property=\"og:description\" content=\"This is something that I waited for a while, in fact since SQL Server 2017 \u2026 and the news came out on Wednesday 09th September 2019. Running Non-Root SQL Server Containers is now possible either on the next version of SQL Server (2019) and it has been backported on SQL Server 2017 as well. Non-root [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-09-29T14:54:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-07-13T13:46:47+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"900\" \/>\n\t<meta property=\"og:image:height\" content=\"300\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Microsoft Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Microsoft Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/\"},\"author\":{\"name\":\"Microsoft Team\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4\"},\"headline\":\"Using non-root SQL Server containers on Docker and K8s\",\"datePublished\":\"2019-09-29T14:54:15+00:00\",\"dateModified\":\"2023-07-13T13:46:47+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/\"},\"wordCount\":1128,\"commentCount\":0,\"image\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg\",\"keywords\":[\"container\",\"kubernetes\",\"peristent volume\",\"persistent volume claim\",\"runAsGroup\",\"runAsUser\",\"Security\",\"SQL Server\"],\"articleSection\":[\"Database Administration &amp; Monitoring\",\"DevOps\",\"Docker\",\"Kubernetes\",\"SQL Server\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/\",\"name\":\"Using non-root SQL Server containers on Docker and K8s - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg\",\"datePublished\":\"2019-09-29T14:54:15+00:00\",\"dateModified\":\"2023-07-13T13:46:47+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#primaryimage\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg\",\"contentUrl\":\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg\",\"width\":900,\"height\":300},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using non-root SQL Server containers on Docker and K8s\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4\",\"name\":\"Microsoft Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g\",\"caption\":\"Microsoft Team\"},\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/microsoft-team\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Using non-root SQL Server containers on Docker and K8s - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/","og_locale":"en_US","og_type":"article","og_title":"Using non-root SQL Server containers on Docker and K8s","og_description":"This is something that I waited for a while, in fact since SQL Server 2017 \u2026 and the news came out on Wednesday 09th September 2019. Running Non-Root SQL Server Containers is now possible either on the next version of SQL Server (2019) and it has been backported on SQL Server 2017 as well. Non-root [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/","og_site_name":"dbi Blog","article_published_time":"2019-09-29T14:54:15+00:00","article_modified_time":"2023-07-13T13:46:47+00:00","og_image":[{"width":900,"height":300,"url":"http:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg","type":"image\/jpeg"}],"author":"Microsoft Team","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Microsoft Team","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/"},"author":{"name":"Microsoft Team","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4"},"headline":"Using non-root SQL Server containers on Docker and K8s","datePublished":"2019-09-29T14:54:15+00:00","dateModified":"2023-07-13T13:46:47+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/"},"wordCount":1128,"commentCount":0,"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg","keywords":["container","kubernetes","peristent volume","persistent volume claim","runAsGroup","runAsUser","Security","SQL Server"],"articleSection":["Database Administration &amp; Monitoring","DevOps","Docker","Kubernetes","SQL Server"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/","url":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/","name":"Using non-root SQL Server containers on Docker and K8s - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#primaryimage"},"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg","datePublished":"2019-09-29T14:54:15+00:00","dateModified":"2023-07-13T13:46:47+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#primaryimage","url":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg","contentUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2022\/04\/163-0-banner-e1569773933862.jpg","width":900,"height":300},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/using-non-root-sql-server-containers-on-docker-and-k8s\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Using non-root SQL Server containers on Docker and K8s"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/bfab48333280d616e1170e7369df90a4","name":"Microsoft Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c44a1a792c059f24055763aa77d80a244467f6eef724a8bd13db8d4a350b7a4c?s=96&d=mm&r=g","caption":"Microsoft Team"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/microsoft-team\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/12835","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/26"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=12835"}],"version-history":[{"count":1,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/12835\/revisions"}],"predecessor-version":[{"id":26685,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/12835\/revisions\/26685"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media\/12836"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=12835"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=12835"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=12835"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=12835"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}