======================== Correct Answer Start ========================
According to the Postgres image documentation you can extend the original image by running a script or an SQL file.
If you would like to do additional initialization in an image derived from this one, add one or more *.sql, *.sql.gz, or *.sh scripts under /docker-entrypoint-initdb.d (creating the directory if necessary). After the entrypoint calls initdb to create the default postgres user and database, it will run any *.sql files and source any *.sh scripts found in that directory to do further initialization before starting the service.
For your Dockerfile, you could do something like this.
FROM postgres:9.6.5
ENV POSTGRES_USER postgres
ENV POSTGRES_PASSWORD xxx
ENV POSTGRES_DB postgres
ADD create-role.sh /docker-entrypoint-initdb.d
ADD localDump.sql /docker-entrypoint-initdb.d
You will also need the create-role.sh script to execute the plsql command
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
CREATE ROLE read_only;
EOSQL
Note that I'm not a SQL DBA, the plsql command is just an example.
======================== Correct Answer End ========================
Original answer left for posterity :
Can you use psql ? Something like that.
FROM postgres:9.6.5
ENV POSTGRES_USER postgres
ENV POSTGRES_PASSWORD xxx
ENV POSTGRES_DB postgres
RUN psql -U postgres -d database_name -c "SQL_QUERY"
ADD localDump.sql /docker-entrypoint-initdb.d
You should find how to run SQL Query for Postgres from bash, and then add a RUN instruction in your Dockerfile.
Answer from Wassim Dhif on Stack OverflowHow to run sql script in sequence using docker compose
t sql - Run SQL script after start of SQL Server on docker - Stack Overflow
psql - How do I run a sql file of inserts through docker run? - Stack Overflow
mysql - Docker, how to run .sql file in an image? - Stack Overflow
If you are going to do pipe redirections in your command, pass it as a string to /bin/sh:
docker exec <container_id> /bin/sh -c 'mysql -u root -ppassword </dummy.sql'
One does not need to copy the script first. If the script is on the host then:
docker exec -i <container_name> mysql -u root -ppassword <mydb> < /path/to/script.sql
Or if the Use db directive is contained inside the script:
docker exec -i <container_name> mysql -u root -ppassword < /path/to/script.sql
RUN gets used to build the layers in an image. CMD is the command that is run when you launch an instance (a "container") of the built image.
Also, if your script depends on those environment variables, if it's an older version of Docker, it might fail because those variables are not defined the way you want them defined!
In older versions of docker the Dockerfile ENV command uses spaces instead of "="
Your Dockerfile should probably be:
FROM microsoft/mssql-server-windows-express
COPY ./create-db.sql .
ENV ACCEPT_EULA Y
ENV SA_PASSWORD ##$wo0RD!
RUN sqlcmd -i create-db.sql
This will create an image containing the database with your password inside it.
(If the SQL file somehow uses the environment variables, this wouldn't make sense as you might as well update the SQL file before you copy it over.) If you want to be able to override the password between the docker build and docker run steps, by using docker run --env sa_password=##$wo0RD! ..., you will need to change the last line to:
CMD sqlcmd -i create-db.sql && .\start -sa_password $env:SA_PASSWORD \
-ACCEPT_EULA $env:ACCEPT_EULA -attach_dbs \"$env:attach_dbs\" -Verbose
Which is a modified version of the CMD line that is inherited from the upstream image.
You can follow this link https://github.com/microsoft/mssql-docker/issues/11. Credits to Robin Moffatt. Change your docker-compose.yml file to contain the following
mssql:
image: microsoft/mssql-server-windows-express
environment:
- SA_PASSWORD=##$wo0RD!
- ACCEPT_EULA=Y
volumes:
# directory with sql script on pc to /scripts/
# - ./data/mssql:/scripts/
- ./create-db.sql:/scripts/
command:
- /bin/bash
- -c
- |
# Launch MSSQL and send to background
/opt/mssql/bin/sqlservr &
# Wait 30 seconds for it to be available
# (lame, I know, but there's no nc available to start prodding network ports)
sleep 30
# Run every script in /scripts
# TODO set a flag so that this is only done once on creation,
# and not every time the container runs
for foo in /scripts/*.sql
do /opt/mssql-tools/bin/sqlcmd -U sa -P $$SA_PASSWORD -l 30 -e -i $$foo
done
# So that the container doesn't shut down, sleep this thread
sleep infinity
to execute commands against a running container use docker exec.
to copy a file (ex: dump.sql) into a container, use docker cp
So your approach might look something like this:
docker cp ./dump.sql pg_test:/docker-entrypoint-initdb.d/dump.sql
docker exec -u postgres pg_test psql postgres postgres -f docker-entrypoint-initdb.d/dump.sql
here it is in generic form:
docker cp ./localfile.sql containername:/container/path/file.sql
docker exec -u postgresuser containername psql dbname postgresuser -f /container/path/file.sql
And note that if you need to seed your database every time it is run, the folder /docker-entrypoint-initdb.d/ does have special significance, if you're using the offical postgres image
You can run a sql command file against a running postgres container via the one liner
cat ./query.sql | docker exec -i <container-name> psql -U <user> -d <database>
without having to copy the file from your host machine to the container.
Change the password of the sql server to be complex enough.
docker run -d -p 1433:1433 -e "sa_password=ComplexPW2019!" -e "ACCEPT_EULA=Y" <sqlserverimageid>
To create the database on startup, try the approach below.
Dockerfile
FROM mcr.microsoft.com/mssql/server:2019-latest
ENV ACCEPT_EULA Y
ENV DB_NAME test
COPY startup.sh /var/opt/mssql/startup.sh
CMD ["bash", "/var/opt/mssql/startup.sh"]
startup.sh
#!/usr/bin/env bash
if ! [ -f /var/opt/mssql/.initialized ] && [ -n "$DB_NAME" ]; then
while ! </dev/tcp/localhost/1433 2>/dev/null; do
sleep 2
done
echo "Creating $DB_NAME database..."
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "$SA_PASSWORD" -d master \
-Q "CREATE DATABASE $DB_NAME"
touch /var/opt/mssql/.initialized
fi &
/opt/mssql/bin/sqlservr
I ended up using a slightly modified version of VDR's solution which waits for the sqlservr to start by checking the logs instead of sleeping 10 seconds:
RUN ( /opt/mssql/bin/sqlservr --accept-eula & ) | grep -q "Service Broker manager has started" \
&& /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'P@ssw0rd' -i /opt/mssql-scripts/000_create_db.sql \
&& pkill sqlservr
From the mssql-server-linux dockerfile, looks like mssql is started on docker run, so you have to modify your last "RUN" command in your dockerfile to start sql-server in the background, run your sql file and stop the sql-server.
RUN /opt/mssql/bin/sqlservr --accept-eula & sleep 10 \
&& /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'P@ssw0rd' -i /opt/mssql-scripts/000_create_db.sql \
&& pkill sqlservr