I have Dockerfile that works with API and MySQL database and it should do migrations:
FROM node
WORKDIR /api
COPY . .
RUN npm install
EXPOSE 3001
VOLUME [ "/api/node_modules" ]
CMD [ "npm", "start" ]
Also, there is a docker-compose file where I have database as a service:
db:
image: mysql
container_name: database
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_PASSWORD: password
MYSQL_DATABASE: testdb
The problem is, I don’t know how to run migrations. Should I do it from docker-compose file or Dockerfile?
I was trying to do something like this in Dockerfile, but it doesn’t seem to be working:
...
CMD [ "knex", "migrate:latest" ]
...
Or:
...
RUN knex migrate:latest
...
2
Answers
I solved this problem, probably in stupid way, but it works. So, what I did is just added this on my API container:
Now, it just restarts container until get connection to database and does all migrations.
Chaining the command or using and entrypoint is less optimal in case you want to horizontally scale your application.
Then all replicas will do the migration, at the same time. It’s likely to not cause real problems, but It’s still not perfect IMO.
Instead, this should be handled separately, as a one shot command when actually required. For example, in Kubernetes in would be good to run a dedicated migration job along with your application release, if the database schema has actually changed.
With compose, there are no jobs, but you can achieve similar behaviour.
Now you row the migration only once and all 3 app replicas wait for the migration to complete before they start up.
In your case, you would use the same image you build from the Dockerfile for both migration and app service. In the migration service you use
knex migrate
and in the app service you usenpm run start
.If you need the migration to even wait for the DB, depends_on might not be sufficient, unless you build in a health check that reflects if the database is actually ready to accept a connection. If you have a health check, then you can use the condition
service_healthy
.For example, you could dome something like this.
You can health check logs by doing a container inspect.
If you don’t want to use a health check, you can also use third party solutions like https://github.com/Eficode/wait-for.