Skip to content

Instantly share code, notes, and snippets.

@arkadijs
Last active August 29, 2015 14:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arkadijs/5315aebdcbf6696a6d24 to your computer and use it in GitHub Desktop.
Save arkadijs/5315aebdcbf6696a6d24 to your computer and use it in GitHub Desktop.

Docker

Docker-enabled environment

Cloud

ssh -i workshop.pem ubuntu@lxc-1-01.eu.r53.acp.io

Replace 01 in lxc-1-01 with index assigned to you. Download workshop key below.

Installation on Ubuntu Linux

Become root user via sudo -i and execute following commands:

echo 'deb https://get.docker.io/ubuntu docker main' \
    > /etc/apt/sources.list.d/docker.list
# optionally, trust the repo key
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 \
    --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
apt-get update
apt-get install -y lxc-docker
usermod -a -G docker ubuntu

Re-login or su - ubuntu for ubuntu user to receive supplementary docker group.

Ubuntu 12.04

Update to patched 3.13 kernel on Precise:

apt-get install linux-hwe-generic

and reboot.

Other Linux distributions please follow the official instructions.

Docker images

Public images are hosted on Docker Hub Registry. The sources of those images are usually found on GitHub, most notable repositories are:

  1. Official Images
  2. tianon/dockerfiles
  3. Dockefile Project and theirs repos
  4. phusion/baseimage-docker

Pull from central registry

docker pull centos:latest
docker pull phusion/baseimage:latest
docker images

Make sure to use :latest!

Load from tar files

Via local Wi-Fi:

wget -O - http://192.168.1.3/docker/centos.tar.gz \
    | gzip -dc \
    | docker load
wget -O - http://192.168.1.3/docker/phusion-baseimage.tar.gz | gzip -dc | docker load

In the cloud:

wget -O - http://lxc-1-00.eu.r53.acp.io/docker/centos.tar.gz | gzip -dc | docker load
wget -O - http://lxc-1-00.eu.r53.acp.io/docker/phusion-baseimage.tar.gz | gzip -dc | docker load

Or ask me for a flash-drive.

There are more images to pull that we will need later: registry, konradkleine/docker-registry-frontend.

Shell in container

docker run -ti --rm centos /bin/bash
  # in the container
  ps auxw
  df -h
  exit

Service in container

Let create our first Dockerfile!

mkdir mine-service && cd mine-service
cat > Dockerfile <<EOF
FROM centos:latest
ADD run.sh /
CMD [ "/run.sh" ]
EOF

Create run.sh:

echo -e '#!/bin/sh\necho Hello World!' > run.sh
chmod +x run.sh

Build the image and play around:

docker build .
docker images -a
# tag the latest image by CREATED column
docker tag c6dc2598a3c1 mine/service:devel
docker images -a
docker run --rm mine/service:devel
docker rmi mine/service:devel

Supervised service in rich container

Single-process container has some problems explained by Phusion people on phusion/baseimage website. You may want to read an alternative opinion.

Let rebase to phusion/baseimage and tell supervisor to monitor our process:

FROM phusion/baseimage:0.9.15
MAINTAINER Name <email>
ADD run.sh /etc/service/hello/run
RUN groupadd -r hello \
        && useradd -r -g hello hello
VOLUME /data

Modify run.sh:

#!/bin/sh
u=hello:hello
chown $u /data
exec chpst -u $u /bin/sh -c "for i in 1 2 3 4 5; do echo Hello ${HELLO_OPTIONS:-World}! -- \$i; sleep 3; done; date >/data/date.txt"

Try it!

docker build -t mine/service:devel .
docker run --name hello -ti \
    -e HELLO_OPTIONS="Docker World" \
    -v /tmp:/data \
    mine/service:devel \
    /sbin/my_init -- bash -l
  # in the container
  ps auxw
  exit
docker ps -a
docker rm hello
docker rmi mine/service:devel
cat /tmp/date.txt
ls -l /tmp/date.txt # notice owner of the file

More phusion/baseimage examples:

You may be also interested in ubuntu-upstart and fedora/systemd-systemd.

Pushing images to central registry

Signup for Docker Hub access. Then login and push the image:

docker login
docker build -t user/service:1.0.0 .
docker tag user/service:1.0.0 user/service:latest
docker push user/service

Private registry

mkdir /tmp/registry
docker run --name registry -p 5000:5000 -v /tmp/registry:/tmp/registry \
    -e SETTINGS_FLAVOR=local \
    -e SEARCH_BACKEND=sqlalchemy \
    registry

More usage info at Registry repository.

Let push some image into it, in another terminal:

docker tag user/service localhost:5000/service
docker push localhost:5000/service
ls -l /tmp/registry/*

Pull it back and run:

docker images
docker rmi localhost:5000/service user/service user/service:1.0.0
docker pull localhost:5000/service
docker run --rm localhost:5000/service

Let add an UI to our registry:

docker run --name registry-front -P \
    -e ENV_DOCKER_REGISTRY_HOST=lxc-1-01.eu.r53.acp.io \
    -e ENV_DOCKER_REGISTRY_PORT=5000 \
    konradkleine/docker-registry-frontend
docker port registry-front 80

For the 0.0.0.0:49153 output of port command, go and open http://lxc-1-01.eu.r53.acp.io:49153/ in the browser.

There is also another UI available:

docker inspect registry | grep IPAddress # got 172.17.0.2
docker run --name registry-ui -p 80:8080 \
    -e REG1=http://172.17.0.2:5000/v1/ \
    atcol/docker-registry-ui

LXC

LXC-enabled environment

Become root, then:

apt-add-repository ppa:ubuntu-lxc/stable
apt-get update
apt-get install -y lxc lxc-templates cgmanager cgroup-lite cloud-utils

Remember to update kernel to 3.13+.

Setting up the network

Check /etc/lxc/default.conf to contain:

lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
lxc.network.hwaddr = 00:16:3e:xx:xx:xx

(The above is Ubuntu default)

Bare-metal network

Virtualized network

Enable Promiscuous Mode in VirtualBox.

Cloud network

Creating OS image

lxc-create -n test -t ubuntu-cloud \
    -- -r precise -s daily # optional, use 12.04 with latest updates
  # add
  #   -T https://cloud-images.ubuntu.com/precise/20141015/precise-server-cloudimg-amd64-root.tar.gz
  # in case lxc-create cannot find ubuntu-cloudimg-query or do
  #   apt-get install cloud-utils
lxc-start -n test -d
lxc-ls -f
lxc-attach -n test
  # in the container
  ping google.com
  ip addr ls dev eth0
  ps auxw
  exit
lxc-destroy -n test -f

Look for OS templates in /usr/share/lxc/templates/.

More LXC examples:

#cloud-config
disable_root: false
repo_upgrade: none
bootcmd:
- [ cloud-init-per, instance, mkswap, /sbin/mkswap, /dev/xvdb ]
mounts:
- [ /dev/xvdb, swap, swap ]
- [ none, /tmp, tmpfs, size=4G ]
output: { all: '| tee -a /var/log/cloud-init-output.log' }
#!/bin/sh
region=eu-west-1
stack=lxc-1
set -e
autoscaling_group=LXCServerAutoScale
initial_delay=60
retry_delay=10
retry_count=10
aws --region $region cloudformation create-stack \
--stack-name $stack \
--template-body file://cloudformation.template \
--tags Key=Name,Value=$stack \
--parameters \
ParameterKey=InstanceType,ParameterValue=t2.small ParameterKey=KeyPair,ParameterValue=workshop ParameterKey=CloudConfig,ParameterValue="$(base64 cloud-config.yml)"
set +e
echo Waiting for CloudFormation...
sleep $initial_delay
i=0
problem () {
echo "CloudFormation error, waited $(($initial_delay+$i*$retry_delay)) seconds"
aws --output table --region $region cloudformation describe-stack-resources --stack $stack
exit 1
}
while :; do
status=$(aws --region $region cloudformation describe-stack-resource --stack $stack --logical-resource-id $autoscaling_group 2>&1 | grep ResourceStatus)
if test -n "$status"; then
if echo "$status" | grep CREATE_COMPLETE; then break; fi
if echo "$status" | grep -Ev '(CREATE_|Resource creation Initiated)'; then problem; fi
fi
i=$(($i+1))
if test $i -gt $retry_count; then problem; fi
echo Still waiting...
sleep $retry_delay
done
first_node=$(aws --region $region ec2 describe-instances --filters "Name=tag-value,Values=$stack" --output text --query 'Reservations[0].Instances[0].PublicDnsName')
echo "\nLXC cluster is ready!"
echo "Do 'ssh ubuntu@$first_node' now."
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Ubuntu 14.04 pool on EC2",
"Mappings" : {
"RegionMap" : {
"ap-northeast-1" : {
"AMI" : "ami-e74b60e6"
},
"sa-east-1" : {
"AMI" : "ami-69d26774"
},
"ap-southeast-1" : {
"AMI" : "ami-d6e7c084"
},
"ap-southeast-2" : {
"AMI" : "ami-1711732d"
},
"cn-north-1" : {
"AMI" : "ami-c642d0ff"
},
"us-east-1" : {
"AMI" : "ami-9eaa1cf6"
},
"us-west-1" : {
"AMI" : "ami-076e6542"
},
"us-west-2" : {
"AMI" : "ami-3d50120d"
},
"eu-west-1" : {
"AMI" : "ami-f0b11187"
}
}
},
"Parameters": {
"InstanceType" : {
"Description" : "EC2 HVM instance type (t2.small, m3.medium, etc).",
"Type" : "String",
"Default" : "m3.medium",
"AllowedValues" : [ "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "c3.large","c3.xlarge", "c3.2xlarge", "c3.4xlarge","c3.8xlarge", "cc2.8xlarge","cr1.8xlarge","hi1.4xlarge", "hs1.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "r3.large", "r3.xlarge", "r3.2xlarge","r3.4xlarge", "r3.8xlarge", "t2.micro", "t2.small", "t2.medium" ],
"ConstraintDescription" : "Must be a valid EC2 HVM instance type."
},
"ClusterSize": {
"Default": "1",
"MinValue": "1",
"MaxValue": "16",
"Description": "Number of nodes in cluster (1-16).",
"Type": "Number"
},
"CloudConfig": {
"Description": "The cloud-config.yml for the cluster.",
"Type": "String"
},
"KeyPair" : {
"Description" : "The name of an EC2 Key Pair to allow SSH access to the instance.",
"Type": "String"
}
},
"Resources": {
"WorkshopSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Workshop SecurityGroup",
"SecurityGroupIngress": [
{"IpProtocol": "icmp","FromPort": "-1", "ToPort": "-1", "CidrIp": "0.0.0.0/0"},
{"IpProtocol": "tcp", "FromPort": "1", "ToPort": "65535", "CidrIp": "0.0.0.0/0"},
{"IpProtocol": "udp", "FromPort": "1", "ToPort": "65535", "CidrIp": "0.0.0.0/0"}
]
}
},
"LXCServerAutoScale": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"AvailabilityZones": {"Fn::GetAZs": ""},
"LaunchConfigurationName": {"Ref": "LXCServerLaunchConfig"},
"MinSize": "1",
"MaxSize": "16",
"DesiredCapacity": {"Ref": "ClusterSize"},
"Tags": [
{"Key": "Name", "Value": { "Ref" : "AWS::StackName" }, "PropagateAtLaunch": true}
]
}
},
"LXCServerLaunchConfig": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]},
"InstanceType": {"Ref": "InstanceType"},
"BlockDeviceMappings": [
{ "DeviceName": "/dev/sda1", "Ebs" : {"VolumeSize": "20", "VolumeType": "gp2", "DeleteOnTermination" : true} },
{ "DeviceName": "/dev/xvdb", "Ebs" : {"VolumeSize": "4", "VolumeType": "gp2", "DeleteOnTermination" : true} }
],
"KeyName": {"Ref": "KeyPair"},
"SecurityGroups": [{"Ref": "WorkshopSecurityGroup"}],
"UserData" : {"Ref": "CloudConfig"}
}
}
}
}
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAqKPEqyWnr7s2lPXj2srINcAS9aeWF4siFXGixElLpSsTejKE2Ye9Y/ckoZV9
4cxtfGdB85t1TjxxxATFOJV5ZuJpl6tf5eEe40jgvsTWl2Rjv3CKnak5gUitTah7WIiX+aJ/4jsa
G0jh9XNKieMc8JE26ye+oKh1lM8PpOFIglC5WBrcgeBhxnGfGu5bHLEUo0znZDZO0peYhfh/3J0j
IsJd8WVH76nOe/mWc9bKg7bQROOU4aAQOL2gs8YvB4vutuIMLaQ8AHDc1lbGqZUE8xTXbiNBWbr7
6kaFCZ6YdN+EnQkfYJgC+blvgIBqmCUA0qxiLrsg5an/t5bWkh6y2wIDAQABAoIBAFe5EPXiWY8d
OLBWFFfcwjbLmlE1AutuUaWL/hpS8kmR1cjr/JVXedpFVkXDiL7rY0yiPflltaij4p4PyTO89XDi
eAEQgYsIBtQ+NcKmi+Ymr4iHF2QaAjLRRm0uJjOQolWWBSX+jn8A86GFfpGplYVCVKoQe6YA22E0
MLQZCGnYjUugT2xleLGmb8tmhQmV1H+MSPa5fLIN0yRKiEc1beVtdfuQNXj5NaEKUcOf+QZjDq9X
ig1zpicx5ELIUfwQqlnMb9D+q9nt24YphZt0ofPVoGV/DZHfIEoJOd4hXMPEqO5PeWoFUJ+FeYwZ
FNcWNALgaROamNCuTOtb7GdrlukCgYEA/vbyphz+tDfsJEblainSz/5s9qHCZrhbOZphLWcIrE/b
i+sKUcLNZ9guvYX3Sa3ixYYqE5d46TnBhtju84PvIJ199LnUh7qxqcxK81AFDnlyZcVyoGYb6JfF
A/q11RCLoNJy+jgYvzU9xEWpPUz4JClg+nxWaJM0GeOHuxJ8zqUCgYEAqVMUgApEeEUMnx87F7YD
hW56mx+QmqW5lGDSSdkaYmwPFQ9uwYLUd3Gbpx7OQ7baDIOjwU5+3TQD5Gnb2E5BA/9fcFB58vDP
q+ED1HQyMs0r2uxvg9TCqTEjXE//jBt78l39xKrUr5KLoCoRSNJQATsm/Dkz/SpYTI7t8MhzQ38C
gYEAgiYw6xa19ezt//6osS60TDRGDwe3opPNDXR+0pxb0wnYum26kM3t6Gp0QY6XEudOcSHxbJrP
v84ZueoW3/ujH3UFjN0nXjmw40pDoDxiuGbKPKUzxCkbafm/Oi7Kjv6pJ+kFhDEKgOB+rSgaIg6e
RGdS98psmWk7GVQKPzZKu3kCgYEAmv43p7S+VDEwin92AhBUTNGCXXiZT1Yf99hg5cRbSHiNncOQ
qIXvop5V0rZ6LLW2BvqA7TPDIQy5+12DJg8LqHMck5y25FDWaAkDDniGcsYoPK9srIoW3fTi319D
FqcZ4BN1dY7CPSyxrpyTUcth/J5+4yYhlr4qMXosB9oU2FUCgYEAoTYtDGFt7w1cDZvI+0sRVU9+
xqoe8Z5anfRnNSAzY3GYNoCxEs0XoxMs96RzjNKtE0e2ccSd0R4B1p1LuKyymAJT1Dn9DbKtKajf
uMKUAsgbjKv5Eo7h8xcniEHxXHueULH+b6Y5a3VIYvvdDCnzABzQLzZJb7PX0AXYUcaIzh8=
-----END RSA PRIVATE KEY-----
@NetRat
Copy link

NetRat commented Oct 17, 2014

Usefull:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment