Trying to mount a db into a mssql docker container
Dockerfile
FROM mcr.microsoft.com/mssql/server:2019-latest
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=Str0ngP@ssw0rd!
ENV MSSQL_TCP_PORT=1433
EXPOSE 1433
COPY mydb.mdf /var/opt/mssql/data/mydb.mdf
COPY mydb_log.ldf /var/opt/mssql/data/mydb_log.ldf
ENTRYPOINT /opt/mssql/bin/sqlservr
EDIT
It seems that the only thing that prevents the image from running as a container is when I add those two COPY
instructions within the Dockerfile
. Everything works fine when I remove the two COPY
.
In fact, it says that it can't copy c:\tempdata\master.mdf
to /var/opt/mssql/data/master.mdf
. But why is that?
Lately, when
Structure
All files are in the same folder on my local machine.
myfolder
/Dockerfile
/mydb.mdf
/mydb_log.ldf
Environment
Windows 10 for Workstation
Docker Desktop 4.5.1 (74721) (
Engine 20.10.12,
Compose 1.29.2,
Kubernetes 1.22.5,
Snyk 1.827.0,
Credential Helper 0.6.4)
Visual Studio Code 1.67.2
Error obtained
The image is built in a flawless fashion, letting believe everything's fine. But when I run it, I get an error:
ERROR: BootstrapSystemDataDirectories() failure (HRESULT 0x8007010b)
To run the image, I type the following command:
docker run -p 1433:1433 myimage
or even
docker run myimage
and both fashions creates the same error.
When I type in:
docker images
I can see:
REPOSITORY TAG IMAGE ID CREATED SIZE
myimage latest ffc13a86b57b 28 seconds ago 2.83GB
Which confirms that the image is correctly created.
FINAL EDIT
I thought I would share the resulting Dockerfile
and final solution.
The Goal
The goal was to take a client's database MDF and LDF files in SQL Server and mount them in a Docker Container to avoid the process of installing a local SQL Server instance which I don't really need.
Lesson LEARNED
As @AlwaysLearning states, the COPY
instructions are processed through the root
user of the container, hence taking ownership over the /var/opt/mssql
. Doing exactly as she/he said solved the problem. So folder's ownership needs to be given back to mssql
user as described in @AlwaysLearning's answer. BIG THX!
Final Solution
The final solution is to be able to mount/attach the client's database files to the containerized instance of SQL Server. For that to work, I needed to write a shell script which does just that.
attach-db.sh
sleep 15s
/opt/mssql-tools/bin/sqlcmd -S . -U sa -P $tr0ngP@ssw0rd! -Q "CREATE DATABASE [mydb] ON (FILENAME = '/var/opt/mssql/data/mydb.mdf'),(FILENAME = '/var/opt/mssql/data/mydb_log.ldf') FOR ATTACH"
This comes from here: Attaching databases via a dockerfile
Dockerfile
FROM mcr.microsoft.com/mssql/server:2019-latest
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=$tr0ngP@ssw0rd!
COPY mydb.mdf /var/opt/mssql/data/mydb.mdf
COPY mydb_log.ldf /var/opt/mssql/data/mydb_log.ldf
COPY attach-db.sh /var/opt/mssql/data/attach-db.sh
ENTRYPOINT /var/opt/mssql/data/attach-db.sh & /opt/mssql/bin/sqlservr
Running the built image
docker run -p 1433:1433 --hostname mydb myimage
Connecting to database
Download and install Azure Data Studio is required to connect to a containerized SQL Server instance.
CodePudding user response:
If you check the logs for the Docker container you'll see that the complete error message is:
2022-06-09 00:12:57.28 Server Setup step is copying system data file 'C:\templatedata\master.mdf' to '/var/opt/mssql/data/master.mdf'.
2022-06-09 00:12:57.33 Server ERROR: Setup FAILED copying system data file 'C:\templatedata\master.mdf' to '/var/opt/mssql/data/master.mdf': 5(Access is denied.)
ERROR: BootstrapSystemDataDirectories() failure (HRESULT 0x80070005)
This happens because the Dockerfile COPY
actions are performed as the root
user which leave the file system objects owned by the root
user as seen with:
$ ls -la /var/opt/mssql/data
total 12
drwxr-xr-x 1 root root 4096 Jun 9 00:12 .
drwxrwx--- 1 root root 4096 Jun 9 00:12 ..
-rw-r--r-- 1 root root 0 Jun 9 00:06 mydb.mdf
-rw-r--r-- 1 root root 0 Jun 9 00:06 mydb_log.ldf
The SQL Server service itself is executed using the mssql
user so now it doesn't have access to the /var/opt/mssql/data
directory to add its own files. You can correct that situation by changing the ownership of the files and directories to the mssql
user, i.e.:
FROM mcr.microsoft.com/mssql/server:2019-latest
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=Str0ngP@ssw0rd!
COPY mydb.mdf /var/opt/mssql/data/mydb.mdf
COPY mydb_log.ldf /var/opt/mssql/data/mydb_log.ldf
USER root
RUN chown -R mssql:root /var/opt/mssql
USER mssql
Now the container will start successfully and you can see that the SQL Server service was able to copy its bootstrap files into the /var/opt/mssql/data
directory:
$ ls -la /var/opt/mssql/data
total 81168
drwxr-xr-x 1 mssql root 4096 Jun 9 00:23 .
drwxrwx--- 1 mssql root 4096 Jun 9 00:23 ..
-rw-r----- 1 mssql root 256 Jun 9 00:23 Entropy.bin
-rw-r----- 1 mssql root 4653056 Jun 9 00:23 master.mdf
-rw-r----- 1 mssql root 2097152 Jun 9 00:23 mastlog.ldf
-rw-r----- 1 mssql root 8388608 Jun 9 00:23 model.mdf
-rw-r----- 1 mssql root 14090240 Jun 9 00:23 model_msdbdata.mdf
-rw-r----- 1 mssql root 524288 Jun 9 00:23 model_msdblog.ldf
-rw-r----- 1 mssql root 524288 Jun 9 00:23 model_replicatedmaster.ldf
-rw-r----- 1 mssql root 4653056 Jun 9 00:23 model_replicatedmaster.mdf
-rw-r----- 1 mssql root 8388608 Jun 9 00:23 modellog.ldf
-rw-r----- 1 mssql root 14090240 Jun 9 00:23 msdbdata.mdf
-rw-r----- 1 mssql root 524288 Jun 9 00:23 msdblog.ldf
-rw-r--r-- 1 mssql root 0 Jun 9 00:06 mydb.mdf
-rw-r--r-- 1 mssql root 0 Jun 9 00:06 mydb_log.ldf
-rw-r----- 1 mssql root 8388608 Jun 9 00:23 tempdb.mdf
-rw-r----- 1 mssql root 8388608 Jun 9 00:23 tempdb2.ndf
-rw-r----- 1 mssql root 8388608 Jun 9 00:23 templog.ldf