skip to Main Content

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?

#this problem has been solved, i using command into k8s resource and it work

- name: main-container
...
  command:
  - bash
  - -c
  args:
  - |
     if [ -f /tmp/update_success ]; then
         do
     else
         # Update failed
         do somethingelse
     done

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search