# Update Docker Containers

```bash
sudo vim /mnt/data/docker/update_all_docker_containers.sh
```

#### 1. Automatic updates

```bash
#!/usr/bin/env bash
set -e

# Our function to update containers based on their base image
update_container() {
    local image=$1
    docker pull $image
    local updated_containers=0

    # Loop through all running containers
    for container in $(docker ps --format "{{.Names}}"); do
        local container_image=$(docker inspect --format '{{.Config.Image}}' "$container")
        
        # We check if the current container's image matches the updated image
        if [[ "$container_image" == "$image" ]]; then
            local latest=$(docker inspect --format "{{.Id}}" $image)
            local running=$(docker inspect --format "{{.Image}}" $container)

            if [[ "$running" != "$latest" ]]; then
                echo "Upgrading $container"
                docker rm -f $container
                docker run --name $container $image
                ((updated_containers++))
            fi
        fi
    done

    if [[ $updated_containers -eq 0 ]]; then
        echo "No containers updated for $image"
    else
        echo "$updated_containers container(s) updated for $image"
    fi
}

# Our main script starts here
# Check for updates to all images used by running containers
for image in $(docker ps --format '{{.Image}}' | sort | uniq); do
    echo "Checking updates for $image"
    update_container $image
done

echo "Container update check complete."
```

#### 2. Preserving configurations during automatic updates

```bash
#!/usr/bin/env bash
set -e

# Function to preserve and update container
preserve_and_update_container() {
    local container=$1
    local image=$(docker inspect --format '{{.Config.Image}}' "$container")
    
    # Pull the latest image version
    docker pull $image

    # Compare image IDs to determine if an update is needed
    local latest_image_id=$(docker inspect --format '{{.Id}}' $image)
    local container_image_id=$(docker inspect --format '{{.Image}}' "$container")

    if [[ "$latest_image_id" != "$container_image_id" ]]; then
        echo "Updating $container..."
        
        # Capture current configurations
        local env_vars=$(docker inspect $container --format '{{range .Config.Env}}{{println .}}{{end}}')
        local volumes=$(docker inspect $container --format '{{range .Mounts}}{{println .Source ":" .Destination}}{{end}}')
        local network=$(docker network ls --filter id=$(docker inspect $container --format '{{.HostConfig.NetworkMode}}') --format '{{.Name}}')
        
        # Remove the outdated container
        docker rm -f $container
        
        # Recreate the container with the same configurations
        docker run -d --name $container $(echo "$env_vars" | xargs -I {} echo --env '{}') $(echo "$volumes" | xargs -I {} echo -v '{}') --network="$network" $image
        echo "$container updated successfully."
    else
        echo "$container is already up to date."
    fi
}

# Iterate over all running containers
for container in $(docker ps --format "{{.Names}}"); do
    preserve_and_update_container $container
done

echo "Container update check complete while preserving existing container configurations."
```

```bash
sudo chmod +x update_all_docker_containers.sh

./update_all_docker_containers.sh
```

#### 3. Crontab

##### Option 1

```bash
crontab -e
```

```
0 3 * * * /mnt/data/docker/update_all_docker_containers.sh
```

##### Option 2

```bash
crontab -e
```

```
0 0 * * * /usr/bin/docker system prune -af
```

##### Option 3

```bash
cd /etc/cron.daily
sudo vim docker-prune
```

```
#!/bin/bash
docker system prune -af  --filter "until=$((30*24))h"
```

```bash
sudo chmod +x /etc/cron.daily/docker-prune
```

#### Test

```bash
run-parts /etc/cron.daily
```