Home > database >  Run the container if the previous container ran with cmd/entrypoint script successfully
Run the container if the previous container ran with cmd/entrypoint script successfully

Time:02-17

Im using docker to run container app A, When i upgrade version of container app A i will upgrade remote db using pgsql with image postgres.

In k8s, i use init container to init images posgres and run script update.sh => If process successfully then run the container app A.

With docker environment, i wonder how to do that same with k8s?

CodePudding user response:

In plain Docker, if you run docker run without the -d option, it will block until the container completes. So you could run this literal sequence as something like

docker network create appnet
docker run -d --name db --net appnet postgres

# Run the migrations
docker run --net appnet -e DB_HOST=db myimage update.sh
if [ $? != 0 ]; then
  echo migrations failed >&2
  exit 1
fi

# Run the main application
docker run -d --name app --net appnet -p 8000:8000 myimage

Docker Compose has no support for workflows like this; it is only able to start a batch of long-running containers in parallel, but not more complex "start A only after B is finished" sequences.

If you're sure you want to run migrations every time every instance of your application starts up (including every replica of a Kubernetes Deployment) then you can also write this sequence into an entrypoint wrapper script in your image. This script can be as little as

#!/bin/sh

# Run migrations
update.sh

# Run the main container command
exec "$@"

and in your Dockerfile, make this script be the ENTRYPOINT

COPY entrypoint.sh .            # should be checked in to source control as executable
ENTRYPOINT ["./entrypoint.sh"]  # must be JSON-array syntax
CMD same CMD as before          # unmodified from the existing Dockerfile

Note that there are several reasons to not want this (if you need to roll back the application, what happens to the database? if you need 16 replicas, does every one try to run migrations on its own?) and I might look into other mechanisms like Helm hooks (specifically in a Kubernetes context) to run the upgrades instead.

CodePudding user response:

You would probably get a better answer if you posted your initContainer, but I would do something like this:

initContainers:
- name: init
...
  command:
  - bash
  - -c
  args:
  - |
     update.sh && touch /tmp/update_success
  volumeMounts:
  - name: tmp
    mountPath: /tmp
containers:
- name: main-container
...
  command:
  - bash
  - -c
  args:
  - |
     if [ -f /tmp/update_success ]; then
         # Update succeeded
         do_whatever
     else
         # Update failed
         do_something_else
     done
  volumeMounts:
  - name: tmp
    mountPath: /tmp
volumes:
- name: tmp
  emptyDir: {}

Also, if your init container exits non-zero, the main container will not run. If that's what you want, just make sure update.sh exits an error code when the update fails, and you don't need the above.

  • Related