1. lxc介绍


容器是一种轻量级的虚拟化技术,与qemu/kvm、VMware、Xen等完全的虚拟化方案相比,LXC更像是加强的“chroot”,因为LXC不但没有没有对硬件设备进行仿真,而且可以与主机共享一模一样的操作系统,所以LXC与solaris的zones和BSD的jails相比,更具优势。

目前,有两个比较方便的管理容器的用户空间的工具:libvirt和lxc。libvirt通过"lxc:///"像管理其他虚拟机驱动一样管理lxc虚拟机。另一个是与libvirt完全独立的LXC,它定义了一些列的命令,可以更灵活的管理和使用lxc。

下面,将以LXC为例来介绍lxc的使用。

2 LXC的安装和使用

(1)LXC的安装



  1. sudo apt-get install lxc

该命令将自动安装LXC依赖的其他软件:

cgroup-lite, lvm2, and debootstrap。如果想使用libvirt来实现lxc的管理,还需要安装 libvirt-bin和libvirt-lxc。

(2)LXC主机端的配置文件介绍


在使用LXC之前,首先对其配置文件进行简单的介绍,以便使大家能更好的理解LXC的工作原理。


a. /etc/lxc/lxc.conf


容器默认的配置文件,如果在创建lxc容器的时候不指定配置文件,将默认使用这个配置文件。主要针 对网络以及命名空间的配置。还有一些其他的配置例子可以在/usr/share/doc/lxc/examples/目录下 找到。


b. /usr/lib/lxc/templates/


该目录下保存了当前LXC支持的各种发行版的linux的模板配置文件,目前主要有:


lxc-ubuntu, lxc-fedora,lxc-opensuse,lxc-debian,lxc-busybox,lxc-sshd,lxc-cloud-ubuntu等。


c. /var/lib/lxc


每个容器的实例存放在这个目录下。


d. /var/cache/lxc


容器实例的cache,当用户创建一种类型的实例后,将会在此目录下cache,再次创建时将不需要从网 上下载,直接采用cache的版本,加速了容器实例的创建过程。




下面来分析下lxc-ubuntu的创建过程(详见最下面的注释说明):


1.  #!/bin/bash
2. 
3.  #
4.  # template script for generating ubuntu container for LXC
5.  #
6.  # This script consolidates and extends the existing lxc ubuntu scripts
7.  #
8. 
9.  # Copyright ?2011 Serge Hallyn <serge.hallyn@canonical.com>
10.  # Copyright ?2010 Wilhelm Meier
11.  # Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
12.  #
13.  # This program is free software; you can redistribute it and/or modify
14.  # it under the terms of the GNU General Public License version 2, as
15.  # published by the Free Software Foundation.
16. 
17.  # This program is distributed in the hope that it will be useful,
18.  # but WITHOUT ANY WARRANTY; without even the implied warranty of
19.  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20.  # GNU General Public License for more details.
21. 
22.  # You should have received a copy of the GNU General Public License along
23.  # with this program; if not, write to the Free Software Foundation, Inc.,
24.  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25.  #
26. 
27.  set -e ##如果命令带非零值返回,立即退出 
28. 
29.  if [ -r /etc/default/lxc ]; then
30.  . /etc/default/lxc #导入一些环境变量
31.  fi
32. 
33.  configure_ubuntu()
34.  {

35.  rootfs=$1
36.  hostname=$2
37.  release=$3
38. 
39.  # configure the network using the dhcp
40.  cat <<EOF > $rootfs/etc/network/interfaces
41.  # This file describes the network interfaces available on your system
42.  # and how to activate them. For more information, see interfaces(5).
43. 
44.  # The loopback network interface
45.  auto lo
46.  iface lo inet loopback
47. 
48.  auto eth0
49.  iface eth0 inet dhcp
50.  EOF
51. 
52.  # set the hostname
53.  cat <<EOF > $rootfs/etc/hostname
54.  $hostname
55.  EOF
56.  # set minimal hosts
57.  cat <<EOF > $rootfs/etc/hosts
58.  127.0.0.1 localhost
59.  127.0.1.1 $hostname
60. 
61.  # The following lines are desirable for IPv6 capable hosts
62.  ::1 ip6-localhost ip6-loopback
63.  fe00::0 ip6-localnet
64.  ff00::0 ip6-mcastprefix
65.  ff02::1 ip6-allnodes
66.  ff02::2 ip6-allrouters
67.  EOF
68. 
69.  if [ ! -f $rootfs/etc/init/container-detect.conf ]; then
70.  # suppress log level output for udev
71.  sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
72. 
73.  # remove jobs for consoles 5 and 6 since we only create 4 consoles in
74.  # this template
75.  rm -f $rootfs/etc/init/tty{5,6}.conf
76.  fi
77. 
78.  if [ -z "$bindhome" ]; then
79.  chroot $rootfs useradd --create-home -s /bin/bash ubuntu
80.  echo "ubuntu:ubuntu" | chroot $rootfs chpasswd
81.  fi
82. 
83.  return 0
84.  }
85. 
86.  # finish setting up the user in the container by injecting ssh key and
87.  # adding sudo group membership.
88.  # passed-in user is either 'ubuntu' or the user to bind in from host.
89.  finalize_user()
90.  {

91.  user=$1
92. 
93.  sudo_version=$(chroot $rootfs dpkg-query -W -f='${Version}' sudo)
94. 
95.  if chroot $rootfs dpkg --compare-versions $sudo_version gt "1.8.3p1-1"; then
96.  groups="sudo"
97.  else
98.  groups="sudo admin"
99.  fi
100. 
101.  for group in $groups; do
102.  chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true
103.  chroot $rootfs adduser ${user} $group >/dev/null 2>&1 || true
104.  done
105. 
106.  if [ -n "$auth_key" -a -f "$auth_key" ]; then
107.  u_path="/home/${user}/.ssh"
108.  root_u_path="$rootfs/$u_path"
109. 
110.  mkdir -p $root_u_path
111.  cp $auth_key "$root_u_path/authorized_keys"
112.  chroot $rootfs chown -R ${user}: "$u_path"
113. 
114.  echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys"
115.  fi
116.  return 0
117.  }
118. 
119.  write_sourceslist()
120.  {

121.  # $1 => path to the rootfs
122.  # $2 => architecture we want to add
123.  # $3 => whether to use the multi-arch syntax or not
124. 
125.  case $2 in
126.  amd64|i386)
127.  MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
128.  SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu}
129.  ;;
130.  *)
131.  MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
132.  SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
133.  ;;
134.  esac
135.  if [ -n "$3" ]; then
136.  cat >> "$1/etc/apt/sources.list" << EOF
137.  deb [arch=$2] $MIRROR ${release} main restricted universe multiverse
138.  deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse
139.  deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse
140.  EOF
141.  else
142.  cat >> "$1/etc/apt/sources.list" << EOF
143.  deb $MIRROR ${release} main restricted universe multiverse
144.  deb $MIRROR ${release}-updates main restricted universe multiverse
145.  deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse
146.  EOF
147.  fi
148.  }
149. 
150.  download_ubuntu()
151.  {

152.  cache=$1
153.  arch=$2
154.  release=$3
155. 
156.  packages=vim,ssh
157.  echo "installing packages: $packages"
158. 
159.  # check the mini ubuntu was not already downloaded
160.  mkdir -p "$cache/partial-$arch"
161.  if [ $? -ne 0 ]; then
162.  echo "Failed to create '$cache/partial-$arch' directory"
163.  return 1
164.  fi
165. 
166.  # download a mini ubuntu into a cache
167.  echo "Downloading ubuntu $release minimal ..."
168.  if [ -n "$(which qemu-debootstrap)" ]; then
169.  qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
170.  else
171.  debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR ##在这里下载制定的linux发行版 
172.  fi
173. 
174.  if [ $? -ne 0 ]; then
175.  echo "Failed to download the rootfs, aborting."
176.  return 1
177.  fi
178. 
179.  # Serge isn't sure whether we should avoid doing this when
180.  # $release == `distro-info -d`
181.  echo "Installing updates"
182.  > $cache/partial-$arch/etc/apt/sources.list
183.  write_sourceslist $cache/partial-$arch/ $arch ##下载完成后,修改source.lst文件,升级和安装软件做准备 
184. 
185. ##改变系统的根目录,执行update,因为,要用新的source.lst
186. chroot "$1/partial-${arch}" apt-get update
187.  if [ $? -ne 0 ]; then
188.  echo "Failed to update the apt cache"
189.  return 1
190.  fi
191.  cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF
192.  #!/bin/sh
193.  exit 101
194.  EOF
195.  chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d
196. 
197.  lxc-unshare -s MOUNT -- chroot "$1/partial-${arch}" apt-get dist-upgrade -y 
198.  ret=$?
199.  rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d
200. 
201.  if [ $ret -ne 0 ]; then
202.  echo "Failed to upgrade the cache"
203.  return 1
204.  fi
205. 
206.  mv "$1/partial-$arch" "$1/rootfs-$arch"
207.  echo "Download complete"
208.  return 0
209.  }
210. 
211.  copy_ubuntu()
212.  {

213.  cache=$1
214.  arch=$2
215.  rootfs=$3
216. 
217.  # make a local copy of the miniubuntu
218.  echo "Copying rootfs to $rootfs ..."
219.  mkdir -p $rootfs
220.  #使用rsync进行镜像的备份,实际相当于镜像的拷贝 
221.  rsync -a $cache/rootfs-$arch/ $rootfs/ || return 1 
222.  return 0
223.  }
224. 
225.  install_ubuntu()
226.  {

227.  rootfs=$1
228.  release=$2
229.  flushcache=$3
230.  cache="/var/cache/lxc/$release"
231.  mkdir -p /var/lock/subsys/
232. 
233.  (
234.  flock -x 200
235.  if [ $? -ne 0 ]; then
236.  echo "Cache repository is busy."
237.  return 1
238.  fi
239. 
240. 
241.  if [ $flushcache -eq 1 ]; then
242.  echo "Flushing cache..."
243.  rm -rf "$cache/partial-$arch"
244.  rm -rf "$cache/rootfs-$arch"
245.  fi
246. 
247.  echo "Checking cache download in $cache/rootfs-$arch ... "
248.  if [ ! -e "$cache/rootfs-$arch" ]; then
249.  download_ubuntu $cache $arch $release ##下载指定版本的系统到cache目录下 
250.  if [ $? -ne 0 ]; then
251.  echo "Failed to download 'ubuntu $release base'"
252.  return 1
253.  fi
254.  fi
255. 
256.  echo "Copy $cache/rootfs-$arch to $rootfs ... "
257. copy_ubuntu $cache $arch $rootfs ##从cache目录下拷贝到真正的根目录下
258.  if [ $? -ne 0 ]; then
259.  echo "Failed to copy rootfs"
260.  return 1
261.  fi
262. 
263.  return 0
264. 
265.  ) 200>/var/lock/subsys/lxc
266. 
267.  return $?
268.  }
269. 
270.  copy_configuration()
271.  {

272.  path=$1
273.  rootfs=$2
274.  name=$3
275.  arch=$4
276.  release=$5
277. 
278.  if [ $arch = "i386" ]; then
279.  arch="i686"
280.  fi
281. 
282.  ttydir=""
283.  if [ -f $rootfs/etc/init/container-detect.conf ]; then
284.  ttydir=" lxc"
285.  fi
286. 
287.  # if there is exactly one veth network entry, make sure it has an
288.  # associated hwaddr.
289.  nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
290.  if [ $nics -eq 1 ]; then
291.  grep -q "^lxc.network.hwaddr" $path/config || cat <<EOF >> $path/config
292.  lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')
293.  EOF
294.  fi
295. 
296.  cat <<EOF >> $path/config
297.  lxc.utsname = $name
298. 
299.  lxc.devttydir =$ttydir
300.  lxc.tty = 4
301.  lxc.pts = 1024
302.  lxc.rootfs = $rootfs
303.  lxc.mount = $path/fstab
304.  lxc.arch = $arch
305.  lxc.cap.drop = sys_module mac_admin
306.  lxc.pivotdir = lxc_putold
307. 
308.  # uncomment the next line to run the container unconfined:
309.  #lxc.aa_profile = unconfined
310. 
311.  lxc.cgroup.devices.deny = a
312.  # Allow any mknod (but not using the node)
313.  lxc.cgroup.devices.allow = c *:* m
314.  lxc.cgroup.devices.allow = b *:* m
315.  # /dev/null and zero
316.  lxc.cgroup.devices.allow = c 1:3 rwm
317.  lxc.cgroup.devices.allow = c 1:5 rwm
318.  # consoles
319.  lxc.cgroup.devices.allow = c 5:1 rwm
320.  lxc.cgroup.devices.allow = c 5:0 rwm
321.  #lxc.cgroup.devices.allow = c 4:0 rwm
322.  #lxc.cgroup.devices.allow = c 4:1 rwm
323.  # /dev/{,u}random
324.  lxc.cgroup.devices.allow = c 1:9 rwm
325.  lxc.cgroup.devices.allow = c 1:8 rwm
326.  lxc.cgroup.devices.allow = c 136:* rwm
327.  lxc.cgroup.devices.allow = c 5:2 rwm
328.  # rtc
329.  lxc.cgroup.devices.allow = c 254:0 rwm
330.  #fuse
331.  lxc.cgroup.devices.allow = c 10:229 rwm
332.  #tun
333.  lxc.cgroup.devices.allow = c 10:200 rwm
334.  #full
335.  lxc.cgroup.devices.allow = c 1:7 rwm
336.  #hpet
337.  lxc.cgroup.devices.allow = c 10:228 rwm
338.  #kvm
339.  lxc.cgroup.devices.allow = c 10:232 rwm
340.  EOF
341. 
342.  cat <<EOF > $path/fstab
343.  proc proc proc nodev,noexec,nosuid 0 0
344.  sysfs sys sysfs defaults 0 0
345.  EOF
346. 
347.  if [ $? -ne 0 ]; then
348.  echo "Failed to add configuration"
349.  return 1
350.  fi
351. 
352.  return 0
353.  }
354. 
355.  trim()
356.  {

357.  rootfs=$1
358.  release=$2
359. 
360.  # provide the lxc service
361.  cat <<EOF > $rootfs/etc/init/lxc.conf
362.  # fake some events needed for correct startup other services
363. 
364.  description "Container Upstart"
365. 
366.  start on startup
367. 
368.  script
369.  rm -rf /var/run/*.pid
370.  rm -rf /var/run/network/*
371.  /sbin/initctl emit stopped JOB=udevtrigger --no-wait
372.  /sbin/initctl emit started JOB=udev --no-wait
373.  end script
374.  EOF
375. 
376.  # fix buggus runlevel with sshd
377.  cat <<EOF > $rootfs/etc/init/ssh.conf
378.  # ssh - OpenBSD Secure Shell server
379.  #
380.  # The OpenSSH server provides secure shell access to the system.
381. 
382.  description "OpenSSH server"
383. 
384.  start on filesystem
385.  stop on runlevel [!2345]
386. 
387.  expect fork
388.  respawn
389.  respawn limit 10 5
390.  umask 022
391.  # replaces SSHD_OOM_ADJUST in /etc/default/ssh
392.  oom never
393. 
394.  pre-start script
395.  test -x /usr/sbin/sshd || { stop; exit 0; }
396.  test -e /etc/ssh/sshd_not_to_be_run && { stop; exit 0; }
397.  test -c /dev/null || { stop; exit 0; }
398. 
399.  mkdir -p -m0755 /var/run/sshd
400.  end script
401. 
402.  # if you used to set SSHD_OPTS in /etc/default/ssh, you can change the
403.  # 'exec' line here instead
404.  exec /usr/sbin/sshd
405.  EOF
406. 
407.  cat <<EOF > $rootfs/etc/init/console.conf
408.  # console - getty
409.  #
410.  # This service maintains a console on tty1 from the point the system is
411.  # started until it is shut down again.
412. 
413.  start on stopped rc RUNLEVEL=[2345]
414.  stop on runlevel [!2345]
415. 
416.  respawn
417.  exec /sbin/getty -8 38400 /dev/console
418.  EOF
419. 
420.  cat <<EOF > $rootfs/lib/init/fstab
421.  # /lib/init/fstab: cleared out for bare-bones lxc
422.  EOF
423. 
424.  # reconfigure some services
425.  if [ -z "$LANG" ]; then
426.  chroot $rootfs locale-gen en_US.UTF-8
427.  chroot $rootfs update-locale LANG=en_US.UTF-8
428.  else
429.  chroot $rootfs locale-gen $LANG
430.  chroot $rootfs update-locale LANG=$LANG
431.  fi
432. 
433.  # remove pointless services in a container
434.  chroot $rootfs /usr/sbin/update-rc.d -f ondemand remove
435. 
436.  chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls u*.conf); do mv $f $f.orig; done'
437.  chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls tty[2-9].conf); do mv $f $f.orig; done'
438.  chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls plymouth*.conf); do mv $f $f.orig; done'
439.  chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls hwclock*.conf); do mv $f $f.orig; done'
440.  chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls module*.conf); do mv $f $f.orig; done'
441. 
442.  # if this isn't lucid, then we need to twiddle the network upstart bits :(
443.  if [ $release != "lucid" ]; then
444.  sed -i 's/^.*emission handled.*$/echo Emitting lo/' $rootfs/etc/network/if-up.d/upstart
445.  fi
446.  }
447. 
448.  post_process()
449.  {

450.  rootfs=$1
451.  release=$2
452.  trim_container=$3
453. 
454.  if [ $trim_container -eq 1 ]; then
455.  trim $rootfs $release
456.  elif [ ! -f $rootfs/etc/init/container-detect.conf ]; then
457.  # Make sure we have a working resolv.conf
458.  cresolvonf="${rootfs}/etc/resolv.conf"
459.  mv $cresolvonf ${cresolvonf}.lxcbak
460.  cat /etc/resolv.conf > ${cresolvonf}
461. 
462.  # for lucid, if not trimming, then add the ubuntu-virt
463.  # ppa and install lxcguest
464.  if [ $release = "lucid" ]; then
465.  chroot $rootfs apt-get install --force-yes -y python-software-properties
466.  chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa
467.  fi
468. 
469.  chroot $rootfs apt-get update
470.  chroot $rootfs apt-get install --force-yes -y lxcguest
471. 
472.  # Restore old resolv.conf
473.  rm -f ${cresolvonf}
474.  mv ${cresolvonf}.lxcbak ${cresolvonf}
475.  fi
476. 
477.  # If the container isn't running a native architecture, setup multiarch
478.  if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then
479.  dpkg_version=$(chroot $rootfs dpkg-query -W -f='${Version}' dpkg)
480.  if chroot $rootfs dpkg --compare-versions $dpkg_version ge "1.16.2"; then
481.  chroot $rootfs dpkg --add-architecture ${hostarch}
482.  else
483.  mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d
484.  echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch
485.  fi
486. 
487.  # Save existing value of MIRROR and SECURITY_MIRROR
488.  DEFAULT_MIRROR=$MIRROR
489.  DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR
490. 
491.  # Write a new sources.list containing both native and multiarch entries
492.  > ${rootfs}/etc/apt/sources.list
493.  write_sourceslist $rootfs $arch "native"
494. 
495.  MIRROR=$DEFAULT_MIRROR
496.  SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR
497.  write_sourceslist $rootfs $hostarch "multiarch"
498. 
499.  # Finally update the lists and install upstart using the host architecture
500.  chroot $rootfs apt-get update
501.  chroot $rootfs apt-get install --force-yes -y --no-install-recommends upstart:${hostarch} mountall:${hostarch} iproute:${hostarch} isc-dhcp-client:${hostarch}
502.  fi
503. 
504.  # rmdir /dev/shm for containers that have /run/shm
505.  # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
506.  # get bind mounted to the host's /run/shm. So try to rmdir
507.  # it, and in case that fails move it out of the way.
508.  if [ -d $rootfs/run/shm ]; then
509.  [ -d "$rootfs/dev/shm" ] && rmdir $rootfs/dev/shm
510.  [ -e "$rootfs/dev/shm" ] && mv $rootfs/dev/shm $rootfs/dev/shm.bak
511.  ln -s /run/shm $rootfs/dev/shm
512.  fi
513.  }
514. 
515.  do_bindhome()
516.  {

517.  rootfs=$1
518.  user=$2
519. 
520.  # copy /etc/passwd, /etc/shadow, and /etc/group entries into container
521.  pwd=`getent passwd $user` || { echo "Failed to copy password entry for $user"; false; }
522.  echo $pwd >> $rootfs/etc/passwd
523. 
524.  # make sure user's shell exists in the container
525.  shell=`echo $pwd | cut -d: -f 7`
526.  if [ ! -x $rootfs/$shell ]; then
527.  echo "shell $shell for user $user was not found in the container."
528.  pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1`
529.  echo "Installing $pkg"
530.  chroot $rootfs apt-get --force-yes -y install $pkg
531.  fi
532. 
533.  shad=`getent shadow $user`
534.  echo "$shad" >> $rootfs/etc/shadow
535. 
536.  # bind-mount the user's path into the container's /home
537.  h=`getent passwd $user | cut -d: -f 6`
538.  mkdir -p $rootfs/$h
539. 
540.  # use relative path in container
541.  h2=${h#/}
542.  while [ ${h2:0:1} = "/" ]; do
543.  h2=${h2#/}
544.  done
545.  echo "$h $h2 none bind 0 0" >> $path/fstab
546. 
547.  # Make sure the group exists in container
548.  grp=`echo $pwd | cut -d: -f 4` # group number for $user
549.  grpe=`getent group $grp` || return 0 # if host doesn't define grp, ignore in container
550.  chroot $rootfs getent group "$grpe" || echo "$grpe" >> $rootfs/etc/group
551.  }
552. 
553.  usage()
554.  {

555.  cat <<EOF
556.  $1 -h|--help [-a|--arch] [-b|--bindhome <user>] [--trim] [-d|--debug]
557.  [-F | --flush-cache] [-r|--release <release>] [ -S | --auth-key <keyfile>]
558.  release: the ubuntu release (e.g. precise): defaults to host release on ubuntu, otherwise uses latest LTS
559.  trim: make a minimal (faster, but not upgrade-safe) container
560.  bindhome: bind <user>'s home into the container
561.  The ubuntu user will not be created, and <user> will have
562.  sudo access.
563.  arch: the container architecture (e.g. amd64): defaults to host arch
564.  auth-key: SSH Public key file to inject into container
565.  EOF
566.  return 0
567.  }
568. 
569.  options=$(getopt -o a:b:hp:r:xn:FS:d -l arch:,bindhome:,help,path:,release:,trim,name:,flush-cache,auth-key:,debug -- "$@")
570.  if [ $? -ne 0 ]; then
571.  usage $(basename $0)
572.  exit 1
573.  fi
574.  eval set -- "$options"
575. 
576.  release=precise # Default to the last Ubuntu LTS release for non-Ubuntu systems
577.  if [ -f /etc/lsb-release ]; then
578.  . /etc/lsb-release
579.  if [ "$DISTRIB_ID" = "Ubuntu" ]; then
580.  release=$DISTRIB_CODENAME
581.  fi
582.  fi
583. 
584.  bindhome=
585.  arch=$(arch)
586. 
587.  # Code taken from debootstrap
588.  if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
589.  arch=`/usr/bin/dpkg --print-architecture`
590.  elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
591.  arch=`/usr/bin/udpkg --print-architecture`
592.  else
593.  arch=$(arch)
594.  if [ "$arch" = "i686" ]; then
595.  arch="i386"
596.  elif [ "$arch" = "x86_64" ]; then
597.  arch="amd64"
598.  elif [ "$arch" = "armv7l" ]; then
599.  arch="armel"
600.  fi
601.  fi
602. 
603.  debug=0
604.  trim_container=0
605.  hostarch=$arch
606.  flushcache=0
607.  while true
608.  do
609.  case "$1" in
610.  -h|--help) usage $0 && exit 0;;
611.  -p|--path) path=$2; shift 2;;
612.  -n|--name) name=$2; shift 2;;
613.  -F|--flush-cache) flushcache=1; shift 1;;
614.  -r|--release) release=$2; shift 2;;
615.  -b|--bindhome) bindhome=$2; shift 2;;
616.  -a|--arch) arch=$2; shift 2;;
617.  -x|--trim) trim_container=1; shift 1;;
618.  -S|--auth-key) auth_key=$2; shift 2;;
619.  -d|--debug) debug=1; shift 1;;
620.  --) shift 1; break ;;
621.  *) break ;;
622.  esac
623.  done
624. 
625.  if [ $debug -eq 1 ]; then
626.  set -x
627.  fi
628. 
629.  if [ -n "$bindhome" ]; then
630.  pwd=`getent passwd $bindhome`
631.  if [ $? -ne 0 ]; then
632.  echo "Error: no password entry found for $bindhome"
633.  exit 1
634.  fi
635.  fi
636. 
637. 
638.  if [ "$arch" == "i686" ]; then
639.  arch=i386
640.  fi
641. 
642.  if [ $hostarch = "i386" -a $arch = "amd64" ]; then
643.  echo "can't create amd64 container on i386"
644.  exit 1
645.  fi
646. 
647.  type debootstrap
648.  if [ $? -ne 0 ]; then
649.  echo "'debootstrap' command is missing"
650.  exit 1
651.  fi
652. 
653.  if [ -z "$path" ]; then
654.  echo "'path' parameter is required"
655.  exit 1
656.  fi
657. 
658.  if [ "$(id -u)" != "0" ]; then
659.  echo "This script should be run as 'root'"
660.  exit 1
661.  fi
662. 
663.  rootfs=$path/rootfs
664. ##执行的第一个操作,rootfs文件系统挂载点,flushcache创建cache的目录,release创建实例的版本
665.  install_ubuntu $rootfs $release $flushcache  
666.  if [ $? -ne 0 ]; then
667.  echo "failed to install ubuntu $release"
668.  exit 1
669.  fi
670. 
671.  configure_ubuntu $rootfs $name $release ##将镜像从cache拷贝到真正的rootfs 
672.  if [ $? -ne 0 ]; then
673.  echo "failed to configure ubuntu $release for a container"
674.  exit 1
675.  fi
676. 
677. copy_configuration $path $rootfs $name $arch $release ##在根目录下生成config文件,并在fstab中挂载/proc和/fs
678.  if [ $? -ne 0 ]; then
679.  echo "failed write configuration file"
680.  exit 1
681.  fi




##配置resolv.conf,并在新生成的镜像中安装一些必要的软件,如:lxcguest



    1. post_process $rootfs $release $trim_container
    2. 
    3.  if [ -n "$bindhome" ]; then
    4.  do_bindhome $rootfs $bindhome
    5.  finalize_user $bindhome
    6.  else
    7.  finalize_user ubuntu ##创建用户/属组,配置ssh用户名和密码 
    8.  fi
    9. 
    10.  echo ""
    11.  echo "##"
    12.  echo "# The default user is 'ubuntu' with password 'ubuntu'!"
    13.  echo "# Use the 'sudo' command to run tasks as root in the container."
    14.  echo "##"
    15.  echo ""


    lxc创建ubuntu虚拟机的详细过程参见上面红色注释!




    LXC的其他内容将会在后面的文章中继续介绍!