Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I run a docker container and commit the changes once a script completes?

I want to set up a cron job to run a set of commands inside a docker container and then commit the changes to the docker image. I'm able to run the container as a daemon and get the container ID using this command:

CONTAINER_ID=$(sudo docker run -d my-image /bin/sh -c "sleep 10")

but I'm having trouble with the second part--committing the changes to the image once the sleep 10 command completes. Is there a way for me to tell when the docker container is about to be killed and run another command before it is?

EDIT: As an alternative, is there a way to trigger ctrl-p-q via a shell script in the container to leave the container running but return to the host?

like image 492
mrdziuban Avatar asked Jun 02 '15 22:06

mrdziuban


4 Answers

There are following ways to persist container data:

  1. Docker volumes

  2. Docker commit

    a) create container from ubuntu image and run a bash terminal.

       $ docker run -i -t ubuntu:14.04 /bin/bash
    

    b) Inside the terminal install curl

       # apt-get update
       # apt-get install curl
    

    c) Exit the container terminal

       # exit
    

    d) Take a note of your container id by executing following command :

       $ docker ps -a
    

    e) save container as new image

       $ docker commit <container_id> new_image_name:tag_name(optional)
    

    f) verify that you can see your new image with curl installed.

       $ docker images           
    
       $ docker run -it new_image_name:tag_name bash
          # which curl
            /usr/bin/curl
    
like image 168
kalyani chaudhari Avatar answered Nov 13 '22 08:11

kalyani chaudhari


Run it in the foreground, not as daemon. When it ends the script that launched it takes control and commits/push it

like image 8
gmuslera Avatar answered Nov 13 '22 10:11

gmuslera


I didn't find any of these answers satisfying, as my goal was to 1) launch a container, 2) run a setup script, and 3) capture/store the state after setup, so I can instantly run various scripts against that state later. And all in a local, automated, continuous integration environment (e.g. scripted and non-interactive).

Here's what I came up with (and I run this in Travis-CI install section) for setting up my test environment:

#!/bin/bash

# Run a docker with the env boot script
docker run ubuntu:14.04 /path/to/env_setup_script.sh

# Get the container ID of the last run docker (above)
export CONTAINER_ID=`docker ps -lq`

# Commit the container state (returns an image_id with sha256: prefix cut off)
# and write the IMAGE_ID to disk at ~/.docker_image_id
(docker commit $CONTAINER_ID | cut -c8-) > ~/.docker_image_id

Note that my base image was ubuntu:14.04 but yours could be any image you want.

With that setup, now I can run any number of scripts (e.g. unit tests) against this snapshot (for Travis, these are in my script section). e.g.:

docker run `cat ~/.docker_image_id` /path/to/unit_test_1.sh
docker run `cat ~/.docker_image_id` /path/to/unit_test_2.sh
like image 3
Jeff Ward Avatar answered Nov 13 '22 10:11

Jeff Ward


Try this if you want an auto commit for all which are running. Put this in a cron or something, if this helps

#!/bin/bash
for i in `docker ps|tail -n +2|awk '{print $1}'`; do docker commit -m "commit new change" $i; done
like image 1
Phan Dolphy Avatar answered Nov 13 '22 09:11

Phan Dolphy