1
0
mirror of https://github.com/phusion/baseimage-docker.git synced 2026-03-26 12:29:07 +00:00

Compare commits

..

20 Commits

Author SHA1 Message Date
Hongli Lai (Phusion)
009ed4bd5e Release version 0.9.2 2013-12-11 21:56:29 +01:00
Hongli Lai
5a65631322 Merge pull request #2 from jorisvddonk/patch-1
Fixed SFTP not working
2013-12-06 05:14:35 -08:00
Joris van de Donk
0bcc88828e Fixed SFTP not working
sftp-server isn't located under `/usr/libexec/` (the directory doesn't exist). It's instead located at `/usr/lib/sftp-server`
2013-12-06 13:32:57 +01:00
Hongli Lai (Phusion)
67a9684f0a Fix typos in README 2013-11-20 15:52:18 +01:00
Hongli Lai (Phusion)
c7eb6e98e2 Revert "Document another reason why SSH access is important"
This reverts commit c51ba582e9.
2013-11-13 12:13:06 +01:00
Hongli Lai (Phusion)
c51ba582e9 Document another reason why SSH access is important 2013-11-13 11:42:21 +01:00
Hongli Lai (Phusion)
5293343735 Update README again 2013-11-13 01:04:53 +01:00
Hongli Lai (Phusion)
12e0c8f601 Update README again 2013-11-13 00:07:26 +01:00
Hongli Lai (Phusion)
22fc313d91 Make the description clearer to people who are not familiar with the problem domain 2013-11-12 23:58:05 +01:00
Hongli Lai (Phusion)
4156ab3393 Update README 2013-11-12 23:26:37 +01:00
Hongli Lai (Phusion)
243e2bf58d Update Changelog 2013-11-12 23:03:56 +01:00
Hongli Lai (Phusion)
c7f260d831 Document the consequences of letting processes be killed with SIGKILL 2013-11-12 23:01:37 +01:00
Hongli Lai (Phusion)
df4bfa3d53 Explain that our init process performs shutdown correctly 2013-11-12 22:54:57 +01:00
Hongli Lai (Phusion)
57715ea445 Bump version to 0.9.1 2013-11-12 22:41:39 +01:00
Hongli Lai (Phusion)
99306bcfcd Correctly handle Docker shutdown.
When a container is stopped with 'docker stop', SIGTERM is sent to the
init process. Unfortunately neither bash nor runit-init handle that correctly,
so we write our own init system in Python that also waits for all services to
shutdown.
2013-11-12 22:36:55 +01:00
Hongli Lai (Phusion)
7b4e2b6d77 Add another disadvantage 2013-11-12 22:36:51 +01:00
Hongli Lai (Phusion)
941ba8947e 'make release' should warn if main image not yet build 2013-11-12 17:55:35 +01:00
Hongli Lai (Phusion)
91907f043c Fix README 2013-11-12 15:44:53 +01:00
Hongli Lai (Phusion)
ae570445c6 Link to Docker registry 2013-11-12 13:20:40 +01:00
Hongli Lai (Phusion)
a208c5d1d7 Add SSH instructions 2013-11-12 13:18:07 +01:00
5 changed files with 115 additions and 18 deletions

View File

@@ -1,3 +1,11 @@
## 0.9.2 (release date: 2013-12-11)
* Fixed SFTP support. Thanks Joris van de Donk!
## 0.9.1 (release date: 2013-11-12)
* Improved init process script (`/sbin/my_init`): it now handles shutdown correctly. Previously, `docker stop` would not have any effect on `my_init`, causing the whole container to be killed with SIGKILL. The new init process script gracefully shuts down all runit services, then exits.
## 0.9.0 (release date: 2013-11-12) ## 0.9.0 (release date: 2013-11-12)
* Initial release * Initial release

View File

@@ -1,5 +1,5 @@
NAME = phusion/baseimage NAME = phusion/baseimage
VERSION = 0.9.0 VERSION = 0.9.2
.PHONY: all build tag_latest release .PHONY: all build tag_latest release
@@ -12,5 +12,6 @@ tag_latest:
docker tag $(NAME):$(VERSION) $(NAME):latest docker tag $(NAME):$(VERSION) $(NAME):latest
release: tag_latest release: tag_latest
@if ! docker images phusion/baseimage | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME) version $(VERSION) is not yet built. Please run 'make build'"; false; fi
docker push $(NAME) docker push $(NAME)
@echo "*** Don't forget to create a tag. git tag rel-$(VERSION) && git push origin rel-$(VERSION)" @echo "*** Don't forget to create a tag. git tag rel-$(VERSION) && git push origin rel-$(VERSION)"

View File

@@ -1,19 +1,28 @@
# A minimal Docker base image with a correct and usable system # A minimal Ubuntu base image modified for Docker-friendliness
Baseimage-docker is a [Docker](http://www.docker.io) image meant to serve as a good base for any other Docker container. It contains a minimal base system with the most important things already installed and set up correctly. Baseimage-docker is a special [Docker](http://www.docker.io) image that is configured for correct use within Docker containers. It is Ubuntu, plus modifications for Docker-friendliness. You can use it as a base for your own Docker images.
Baseimage-docker is available for pulling from on [the Docker registry](https://index.docker.io/u/phusion/baseimage/)!
* **Github**: https://github.com/phusion/baseimage-docker * **Github**: https://github.com/phusion/baseimage-docker
* **Discussion forum**: https://groups.google.com/d/forum/passenger-docker * **Discussion forum**: https://groups.google.com/d/forum/passenger-docker
* **Twitter**: https://twitter.com/phusion_nl * **Twitter**: https://twitter.com/phusion_nl
* **Blog**: http://blog.phusion.nl/ * **Blog**: http://blog.phusion.nl/
### What are the problems with the stock Ubuntu base image?
Ubuntu is not designed to be run inside docker. Its init system, Upstart, assumes that it's running on either real hardware or virtualized hardware, but not inside a Docker container. But inside a container you don't want a full system anyway, you want a minimal system. But configuring that minimal system for use within a container has many strange corner cases that are hard to get right if you are not intimately familiar with the Unix system model. This can cause a lot of strange problems.
Baseimage-docker gets everything right. The "Contents" section describes all the things that it modifies.
### Why use baseimage-docker? ### Why use baseimage-docker?
Why use baseimage-docker instead of doing everything yourself in Dockerfile? You can configure the stock `ubuntu` image yourself from your Dockerfile, so why bother using baseimage-docker?
* Configuring the base system for Docker-friendliness is no easy task. As stated before, there are many corner cases. By the time that you've gotten all that right, you've reinvented baseimage-docker. Using baseimage-docker will save you from this effort.
* It reduces the time needed to write a correct Dockerfile. You won't have to worry about the base system and can focus on your stack and your app. * It reduces the time needed to write a correct Dockerfile. You won't have to worry about the base system and can focus on your stack and your app.
* It sets up the base system **correctly**. It's very easy to get the base system wrong, but this image does everything correctly.
* It reduces the time needed to run `docker build`, allowing you to iterate your Dockerfile more quickly. * It reduces the time needed to run `docker build`, allowing you to iterate your Dockerfile more quickly.
* It reduces download time during redeploys. Docker only needs to download the base image once: during the first deploy. On every subsequent deploys, only the changes you make on top of the base image are downloaded.
## Contents ## Contents
@@ -22,15 +31,15 @@ Why use baseimage-docker instead of doing everything yourself in Dockerfile?
| Component | Why is it included? / Remarks | | Component | Why is it included? / Remarks |
| ---------------- | ------------------- | | ---------------- | ------------------- |
| Ubuntu 12.04 LTS | The base system. | | Ubuntu 12.04 LTS | The base system. |
| A **correct** init process | According to the Unix process model, [the init process](https://en.wikipedia.org/wiki/Init) -- PID 1 -- inherit all [orphaned child processes](https://en.wikipedia.org/wiki/Orphan_process) and must [reap them](https://en.wikipedia.org/wiki/Wait_(system_call)). Most Docker containers do not have an init process that does this correctly, and as a result their containers become filled with [zombie processes](https://en.wikipedia.org/wiki/Zombie_process) over time. Baseimage-docker comes with an init process `/sbin/my_init` that performs reaping correctly. | | A **correct** init process | According to the Unix process model, [the init process](https://en.wikipedia.org/wiki/Init) -- PID 1 -- inherits all [orphaned child processes](https://en.wikipedia.org/wiki/Orphan_process) and must [reap them](https://en.wikipedia.org/wiki/Wait_(system_call). Most Docker containers do not have an init process that does this correctly, and as a result their containers become filled with [zombie processes](https://en.wikipedia.org/wiki/Zombie_process) over time. <br><br>Furthermore, `docker stop` sends SIGTERM to the init process, which is then supposed to stop all services. Unfortunately most init systems don't do this correctly within Docker since they're built for hardware shutdowns instead. This causes processes to be hard killed with SIGKILL, which doesn't give them a chance to correctly deinitialize things. This can cause file corruption. <br><br>Baseimage-docker comes with an init process `/sbin/my_init` that performs both of these tasks correctly. |
| Fixes APT incompatibilities with Docker | See https://github.com/dotcloud/docker/issues/1024. | | Fixes APT incompatibilities with Docker | See https://github.com/dotcloud/docker/issues/1024. |
| syslog-ng | A syslog daemon is necessary so that many services - including the kernel itself - can correctly log to /var/log/syslog. If no syslog daemon is running, a lot of important messages are silently swallowed. <br><br>Only listens locally. | | syslog-ng | A syslog daemon is necessary so that many services - including the kernel itself - can correctly log to /var/log/syslog. If no syslog daemon is running, a lot of important messages are silently swallowed. <br><br>Only listens locally. |
| ssh server | Allows you to easily login to your container to inspect or administer things. <br><br>Password and challenge-response authentication are disabled by default. Only key authentication is allowed.<br>It allows an predefined key by default to make debugging easy. You should replace this ASAP. See instructions. | | ssh server | Allows you to easily login to your container to inspect or administer things. <br><br>Password and challenge-response authentication are disabled by default. Only key authentication is allowed.<br>It allows an predefined key by default to make debugging easy. You should replace this ASAP. See instructions. |
| cron | The cron daemon must be running for cron jobs to work. | | cron | The cron daemon must be running for cron jobs to work. |
| [runit](http://smarden.org/runit/) | For service supervision and management. Much easier to use than SysV init and supports restarting daemons when they crash. Much easier to use and more lightweight than Upstart. | | [runit](http://smarden.org/runit/) | Replaces Ubuntu's Upstart. Used for service supervision and management. Much easier to use than SysV init and supports restarting daemons when they crash. Much easier to use and more lightweight than Upstart. |
| `setuser` | A tool for running a command as another user. Easier to use than `su`, has a smaller attack vector than `sudo`, and unlike `chpst` this tool sets `$HOME` correctly. Available as `/sbin/setuser`. | | `setuser` | A tool for running a command as another user. Easier to use than `su`, has a smaller attack vector than `sudo`, and unlike `chpst` this tool sets `$HOME` correctly. Available as `/sbin/setuser`. |
Baseimage-docker is very lightweight: it only consumes 4 MB of memory. Baseimage-docker is very lightweight: it only consumes 6 MB of memory.
### Wait, I thought Docker is about running a single process in a container? ### Wait, I thought Docker is about running a single process in a container?
@@ -76,7 +85,7 @@ By default, it allows SSH access for the key in `image/insecure_key`. This makes
You can add additional daemons to the image by creating runit entries. You only have to write a small shell script which runs your daemon, and runit will keep it up and running for you, restarting it when it crashes, etc. You can add additional daemons to the image by creating runit entries. You only have to write a small shell script which runs your daemon, and runit will keep it up and running for you, restarting it when it crashes, etc.
The shell script must be called `run`, must be executable, and is to be placed in the directory `/etc/services/<NAME>`. The shell script must be called `run`, must be executable, and is to be placed in the directory `/etc/service/<NAME>`.
Here's an example showing you how to a memached server runit entry can be made. Here's an example showing you how to a memached server runit entry can be made.
@@ -87,11 +96,31 @@ Here's an example showing you how to a memached server runit entry can be made.
exec chpst -u memcache /usr/bin/memcached >>/var/log/memcached.log 2>&1 exec chpst -u memcache /usr/bin/memcached >>/var/log/memcached.log 2>&1
### In Dockerfile: ### In Dockerfile:
RUN mkdir /etc/services/memcached RUN mkdir /etc/service/memcached
ADD redis.sh /etc/services/memcached/run ADD memcached.sh /etc/service/memcached/run
Note that the shell script must run the daemon **without letting it daemonize/fork it**. Usually, daemons provide a command line flag or a config file option for that. Note that the shell script must run the daemon **without letting it daemonize/fork it**. Usually, daemons provide a command line flag or a config file option for that.
### Login in to the container
You can use SSH to login to any container that is based on baseimage-docker.
Start a container based on baseimage-docker (or a container based on an image based on baseimage-docker):
docker run phusion/baseimage
Find out the ID of the container that you just ran:
docker ps
Once you have the ID, look for its IP address with:
docker inspect <ID> | grep IPAddress
Now SSH into the container. In this example we're using [the default insecure key](https://github.com/phusion/baseimage-docker/blob/master/image/insecure_key), but if you're followed the instructions well then you've already replaced that with your own key. You did replace the key, didn't you?
ssh -i insecure_key root@<IP address>
## Building the image yourself ## Building the image yourself
If for whatever reason you want to build the image yourself instead of downloading it from the Docker registry, follow these instructions. If for whatever reason you want to build the image yourself instead of downloading it from the Docker registry, follow these instructions.
@@ -118,7 +147,7 @@ If you want to call the resulting image something else, pass the NAME variable,
## Conclusion ## Conclusion
* Using baseimage-docker? [Tweet about us](https://twitter.com/share) or [follow us on Twitter](https://twitter.com/phusion_nl). * Using baseimage-docker? [Tweet about us](https://twitter.com/share) or [follow us on Twitter](https://twitter.com/phusion_nl).
* Having problems? Please post a message at [the discussion forum](https://groups.google.com/d/forum/passenger-docker). * Having problems? Want to participate in development? Please post a message at [the discussion forum](https://groups.google.com/d/forum/passenger-docker).
* Looking for a more complete base image, one that is ideal for Ruby, Python, Node.js and Meteor web apps? Take a look at [passenger-docker](https://github.com/phusion/passenger-docker). * Looking for a more complete base image, one that is ideal for Ruby, Python, Node.js and Meteor web apps? Take a look at [passenger-docker](https://github.com/phusion/passenger-docker).
[<img src="http://www.phusion.nl/assets/logo.png">](http://www.phusion.nl/) [<img src="http://www.phusion.nl/assets/logo.png">](http://www.phusion.nl/)

View File

@@ -123,7 +123,7 @@ ChallengeResponseAuthentication no
#Banner none #Banner none
# override default of no subsystems # override default of no subsystems
Subsystem sftp /usr/libexec/sftp-server Subsystem sftp /usr/lib/sftp-server
# Example of overriding settings on a per-user basis # Example of overriding settings on a per-user basis
#Match User anoncvs #Match User anoncvs

View File

@@ -1,5 +1,64 @@
#!/bin/bash #!/usr/bin/python2
set -e import os, sys, signal, errno
# No exec. We want bash to be the init process so that it can kill
# zombie processes. def reap_child(signum, frame):
/usr/sbin/runsvdir-start global pid, status, waiting_for_runit
try:
result = os.wait3(os.WNOHANG)
if result is not None and pid == result[0]:
status = result[1]
except OSError:
pass
def stop_runit(signum, frame):
global pid
print("*** Shutting down runit (PID %d)..." % pid)
try:
os.kill(pid, signal.SIGHUP)
except OSError:
pass
# Start runit.
signal.signal(signal.SIGCHLD, reap_child)
print("*** Booting runit...")
pid = os.spawnl(os.P_NOWAIT, "/usr/sbin/runsvdir-start", "/usr/sbin/runsvdir-start")
print("*** Runit started as PID %d" % pid)
signal.signal(signal.SIGTERM, stop_runit)
# Wait for runit, and while waiting, reap any adopted orphans.
done = False
while not done:
try:
this_pid, status = os.waitpid(pid, 0)
done = True
except OSError as e:
if e.errno == errno.EINTR:
# Try again
pass
else:
# The SIGCHLD handler probably caught it.
done = True
# Runit has exited. Reset signal handlers.
print("*** Runit exited with code %s. Waiting for all services to shut down..." % status)
signal.signal(signal.SIGCHLD, signal.SIG_DFL)
signal.signal(signal.SIGTERM, signal.SIG_DFL)
signal.siginterrupt(signal.SIGCHLD, False)
signal.siginterrupt(signal.SIGTERM, False)
# Wait at most 5 seconds for services to shut down.
import time
def shutdown(signum = None, frame = None):
global status
if status is not None:
sys.exit(status)
signal.signal(signal.SIGALRM, shutdown)
signal.alarm(5)
done = False
while not done:
done = os.system("/usr/bin/sv status /etc/service/* | grep -q '^run:'") != 0
if not done:
time.sleep(0.5)
shutdown()