Josheli
  • Home
  • Blog
    • Knob
    • Running
    • Soccer
    • Technology
  • About
Knob , Technology

Loading Files to a Docker Container on Startup

by dv February 7, 2019 No Comments

I recently had the problem where I needed to load files into a Docker container, but only once, and only at the startup of that container. Specifically, these were signing certificates stored in an S3 bucket. Obviously (I hope), we don’t want to bake sensitive certificates and keys into a Docker image, so we need some way to load the files into the container file system at startup. The containers run on AWS Fargate, and Fargate doesn’t support EBS or other persistent storage, so mounting a file system was out. Anyway, here’s how I accomplished the task; let me know if you have a better way.

Docker containers have the notion of “entrypoints”. From the documentation: “An ENTRYPOINT allows you to configure a container that will run as an executable.” Basically, it tells Docker what executable, and with what arguments, to run when the container starts up. Normally, you don’t have to specify this, as your base image usually does. For example, the default php:7.2-apache Dockerfile looks like this:

ENTRYPOINT ["docker-php-entrypoint"]

COPY apache2-foreground /usr/local/bin/
WORKDIR /var/www/html

EXPOSE 80
CMD ["apache2-foreground"]

So, somehow I need to inject my own entrypoint executable, then call the apache cmd. Here’s my Dockerfile:

FROM php:7.2-apache

...other docker commands here...

ENTRYPOINT ["/var/www/my-app-entrypoint.sh"]
CMD ["apache2-foreground"]

Basically, my-app-entrypoint.sh is a copy of the default “docker-php-entrypoint” script, except that I call a PHP script, and I don’t accept apache arguments (don’t use them):

#!/bin/bash
set -e

php -f /var/www/my-app-entrypoint.php

exec "$@"

So now, every time a container based on this image starts up, my PHP script will be run. Here’s the code for that:

<?php
require __DIR__ . '/vendor/autoload.php';

use Aws\S3\S3Client;

$cert_dir = __DIR__ . '/certs';
$s3_objects = array_filter(explode(',', getenv('CERT_FILE_OBJECTS')), 'strlen');

if(!$s3_objects)
{
  error_log('No S3 objects specified.');
  exit(1);
}

if(!file_exists($cert_dir))
{
  mkdir($cert_dir);
}

$s3 = new S3Client([
  'version' => 'latest',
  'region'  => getenv('AWS_REGION')
]);

foreach($s3_objects as $object)
{
  try
  {
    $file = $s3->getObject([
      'Bucket' => getenv('S3_BUCKET'),
      'Key'    => $object,
    ]);

    if(!isset($file['ContentLength']) || empty($file['ContentLength']) || !isset($file['Body']) || empty($file['Body']))
    {
      throw new Exception('Empty object content for ' . $object);
    }
  }
  catch(Exception $e)
  {
    if($e instanceof \Aws\Exception\AwsException)
    {
      $error_message = $e->getAwsRequestId() . '; ' . $e->getAwsErrorType() . '; ' . $e->getAwsErrorCode();
    }
    else
    {
      $error_message = $e->getMessage();
    }

    error_log($error_message);
    exit(1);
  }

  file_put_contents($cert_dir . '/' . basename($object), $file['Body']);
}

It’s pretty simple, but this code is:
1) Checking to see if the cert dir exists, and if not, creating it
2) Using the AWS PHP SDK to grab the certs from an S3 bucket and writing them to the local cert directory
3) Killing the container if the certs aren’t there for some reason (app won’t run without them)

For this to work, you’ll need to set a few environment variables in the container: one for the aws region, one for the bucket name, one for the key/path of the cert files in the bucket, and two for the AWS credentials (AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID).

It’s kind of hacky, but I’ve found a lot of things around running on Docker and AWS feel hacky. Like I said, let me know a better way.

Related Content:

  • Dockerizing PHP apps and deploying to AWS Fargate Part 1 by Dv February 6, 2019 For the day job, I maintain four custom PHP apps in addition to several Drupal sites. Up until a couples…
  • A New, Old Hobby: Self-hosted Services by Dv February 21, 2021 I've recently returned to a hobby of mine ... self-hosting various software services and web applications on a server I…
  • Setting up WordPress to use SSH for Updates by Dv December 18, 2015 Here's how I set up WordPress to seamlessly use SSH, rather than FTP, for updates. Using this method, I never…
  • Laravel: Simple Method for Modules by Dv March 1, 2017 In my day job, I maintain a fairly large-ish Laravel application. It started out as a few separate vanilla PHP…
  • Stupidly Simple, Static, Startpage for Self-hosted Services by Dv February 21, 2021 I mentioned the other day that I've been self-hosting some software services on a server in my basement. Well, I…
It's only fair to share...Share on facebook
Facebook
Share on twitter
Twitter
Share on email
Email
  • Previous Dockerizing PHP apps and deploying to AWS Fargate Part 16 years ago
  • Next No Instagram: “follow” Instagram users without having your own account6 years ago

Leave a Reply

Your email address will not be published. Required fields are marked *

Popular Posts

  • Josheli, What Happened? (55,009)
  • Stupidly Simple, Static, Startpage for Self-hosted Services (29,601)
  • Running a Plex Media Server on an Old Laptop (25,796)
  • Simple Google Photos: A WordPress Plugin (22,729)
  • Only Say True Things (22,071)

Random Read

I, Fade
If I'm going to compete in "endurance" events like triathlons and road races, I should…

Read More

Google Photo
Google Photo
Google Photo
Google Photo

Social Things

  • Family Vance
  • Texas Longhorns News

RSS From Familyvance

  • Snowshoeing at Brainard Lake
  • Fishing and Hiking at Golden Gate Canyon State Park
  • Rainbow Trout Fishing Report at Waneka Lake
  • Weightless Texas-Rig Plastic Worms at Sawhill Ponds and Coot Lake
  • Sawhill Ponds Fishing Report
2025 Josheli. Donna Theme powered by WordPress