diff --git a/Dockerfile b/Dockerfile index 2584d771ee..43f8f64cf1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -72,16 +72,6 @@ RUN cd /usr/local/lvm2 \ && make install_device-mapper # see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL -# Install lxc -ENV LXC_VERSION 1.1.2 -RUN mkdir -p /usr/src/lxc \ - && curl -sSL https://linuxcontainers.org/downloads/lxc/lxc-${LXC_VERSION}.tar.gz | tar -v -C /usr/src/lxc/ -xz --strip-components=1 -RUN cd /usr/src/lxc \ - && ./configure \ - && make \ - && make install \ - && ldconfig - # Install Go ENV GO_VERSION 1.5.1 RUN curl -sSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar -v -C /usr/local -xz diff --git a/Dockerfile.gccgo b/Dockerfile.gccgo index e230ef9ebd..1392e723ed 100644 --- a/Dockerfile.gccgo +++ b/Dockerfile.gccgo @@ -39,16 +39,6 @@ RUN cd /usr/local/lvm2 \ && make install_device-mapper # see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL -# Install lxc -ENV LXC_VERSION 1.1.2 -RUN mkdir -p /usr/src/lxc \ - && curl -sSL https://linuxcontainers.org/downloads/lxc/lxc-${LXC_VERSION}.tar.gz | tar -v -C /usr/src/lxc/ -xz --strip-components=1 -RUN cd /usr/src/lxc \ - && ./configure \ - && make \ - && make install \ - && ldconfig - ENV GOPATH /go:/go/src/github.com/docker/docker/vendor # Get the "docker-py" source so we can run their integration tests diff --git a/Dockerfile.simple b/Dockerfile.simple index 12ee7dde30..507018b07c 100644 --- a/Dockerfile.simple +++ b/Dockerfile.simple @@ -26,7 +26,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ \ aufs-tools \ - lxc \ && rm -rf /var/lib/apt/lists/* ENV AUTO_GOPATH 1 diff --git a/builder/dockerfile/parser/testfiles/docker/Dockerfile b/builder/dockerfile/parser/testfiles/docker/Dockerfile index 4a35625415..9717adbd6f 100644 --- a/builder/dockerfile/parser/testfiles/docker/Dockerfile +++ b/builder/dockerfile/parser/testfiles/docker/Dockerfile @@ -40,7 +40,6 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -yq \ libapparmor-dev \ libcap-dev \ libsqlite3-dev \ - lxc=1.0* \ mercurial \ pandoc \ parallel \ diff --git a/builder/dockerfile/parser/testfiles/docker/result b/builder/dockerfile/parser/testfiles/docker/result index 773b640a9d..d032f9bac4 100644 --- a/builder/dockerfile/parser/testfiles/docker/result +++ b/builder/dockerfile/parser/testfiles/docker/result @@ -1,6 +1,6 @@ (from "ubuntu:14.04") (maintainer "Tianon Gravi <admwiggin@gmail.com> (@tianon)") -(run "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -yq \tapt-utils \taufs-tools \tautomake \tbtrfs-tools \tbuild-essential \tcurl \tdpkg-sig \tgit \tiptables \tlibapparmor-dev \tlibcap-dev \tlibsqlite3-dev \tlxc=1.0* \tmercurial \tpandoc \tparallel \treprepro \truby1.9.1 \truby1.9.1-dev \ts3cmd=1.1.0* \t--no-install-recommends") +(run "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -yq \tapt-utils \taufs-tools \tautomake \tbtrfs-tools \tbuild-essential \tcurl \tdpkg-sig \tgit \tiptables \tlibapparmor-dev \tlibcap-dev \tlibsqlite3-dev \tmercurial \tpandoc \tparallel \treprepro \truby1.9.1 \truby1.9.1-dev \ts3cmd=1.1.0* \t--no-install-recommends") (run "git clone --no-checkout https://git.fedorahosted.org/git/lvm2.git /usr/local/lvm2 && cd /usr/local/lvm2 && git checkout -q v2_02_103") (run "cd /usr/local/lvm2 && ./configure --enable-static_link && make device-mapper && make install_device-mapper") (run "curl -sSL https://golang.org/dl/go1.3.src.tar.gz | tar -v -C /usr/local -xz") diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index bf3eec2d2e..fb17b0ec29 100644 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -1379,7 +1379,6 @@ _docker_run() { --link --log-driver --log-opt - --lxc-conf --mac-address --memory -m --memory-swap diff --git a/contrib/completion/fish/docker.fish b/contrib/completion/fish/docker.fish index e0fbcaa80c..15cde66f02 100644 --- a/contrib/completion/fish/docker.fish +++ b/contrib/completion/fish/docker.fish @@ -135,7 +135,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l help -d 'Pri complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s i -l interactive -d 'Keep STDIN open even if not attached' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l ipc -d 'Default is to create a private IPC namespace (POSIX SysV IPC) for the container' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l link -d 'Add link to another container in the form of <name|id>:alias' -complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l lxc-conf -d '(lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s m -l memory -d 'Memory limit (format: <number>[<unit>], where unit = b, k, m or g)' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l mac-address -d 'Container MAC address (e.g. 92:d0:c6:0a:29:33)' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l memory-swap -d "Total memory usage (memory + swap), set '-1' to disable swap (format: <number>[<unit>], where unit = b, k, m or g)" @@ -324,7 +323,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l help -d 'Print complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s i -l interactive -d 'Keep STDIN open even if not attached' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l ipc -d 'Default is to create a private IPC namespace (POSIX SysV IPC) for the container' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l link -d 'Add link to another container in the form of <name|id>:alias' -complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l lxc-conf -d '(lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s m -l memory -d 'Memory limit (format: <number>[<unit>], where unit = b, k, m or g)' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l mac-address -d 'Container MAC address (e.g. 92:d0:c6:0a:29:33)' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l memory-swap -d "Total memory usage (memory + swap), set '-1' to disable swap (format: <number>[<unit>], where unit = b, k, m or g)" diff --git a/contrib/completion/zsh/_docker b/contrib/completion/zsh/_docker index 69b324c8dc..7beb44f278 100644 --- a/contrib/completion/zsh/_docker +++ b/contrib/completion/zsh/_docker @@ -438,7 +438,6 @@ __docker_subcommand() { "($help)*"{-l=,--label=}"[Set meta data on a container]:label: " "($help)--log-driver=[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs splunk none)" "($help)*--log-opt=[Log driver specific options]:log driver options: " - "($help)*--lxc-conf=[Add custom lxc options]:lxc options: " "($help)--mac-address=[Container MAC address]:MAC address: " "($help)--name=[Container name]:name: " "($help)--net=[Connect a container to a network]:network mode:(bridge none container host)" @@ -541,7 +540,7 @@ __docker_subcommand() { "($help)*--dns-opt=[DNS options to use]:DNS option: " \ "($help)*--default-ulimit=[Set default ulimit settings for containers]:ulimit: " \ "($help)--disable-legacy-registry[Do not contact legacy registries]" \ - "($help -e --exec-driver)"{-e=,--exec-driver=}"[Exec driver to use]:driver:(native lxc windows)" \ + "($help -e --exec-driver)"{-e=,--exec-driver=}"[Exec driver to use]:driver:(native windows)" \ "($help)*--exec-opt=[Set exec driver options]:exec driver options: " \ "($help)--exec-root=[Root of the Docker execdriver]:path:_directories" \ "($help)--fixed-cidr=[IPv4 subnet for fixed IPs]:IPv4 subnet: " \ diff --git a/contrib/docker-engine-selinux/docker.fc b/contrib/docker-engine-selinux/docker.fc index f240937c88..589ee28750 100644 --- a/contrib/docker-engine-selinux/docker.fc +++ b/contrib/docker-engine-selinux/docker.fc @@ -14,10 +14,6 @@ /var/run/docker\.sock -s gen_context(system_u:object_r:docker_var_run_t,s0) /var/run/docker-client(/.*)? gen_context(system_u:object_r:docker_var_run_t,s0) -/var/lock/lxc(/.*)? gen_context(system_u:object_r:docker_lock_t,s0) - -/var/log/lxc(/.*)? gen_context(system_u:object_r:docker_log_t,s0) - /var/lib/docker/init(/.*)? gen_context(system_u:object_r:docker_share_t,s0) /var/lib/docker/containers/.*/hosts gen_context(system_u:object_r:docker_share_t,s0) /var/lib/docker/containers/.*/hostname gen_context(system_u:object_r:docker_share_t,s0) diff --git a/contrib/docker-engine-selinux/docker.if b/contrib/docker-engine-selinux/docker.if index 28b47c8f6c..ca075c05c5 100644 --- a/contrib/docker-engine-selinux/docker.if +++ b/contrib/docker-engine-selinux/docker.if @@ -292,7 +292,6 @@ interface(`docker_filetrans_named_content',` files_pid_filetrans($1, docker_var_run_t, file, "docker.pid") files_pid_filetrans($1, docker_var_run_t, sock_file, "docker.sock") files_pid_filetrans($1, docker_var_run_t, dir, "docker-client") - logging_log_filetrans($1, docker_log_t, dir, "lxc") files_var_lib_filetrans($1, docker_var_lib_t, dir, "docker") filetrans_pattern($1, docker_var_lib_t, docker_share_t, file, "config.env") filetrans_pattern($1, docker_var_lib_t, docker_share_t, file, "hosts") @@ -406,11 +405,6 @@ interface(`staff_stub',` type staff_t; ') ') -interface(`virt_stub_lxc',` - gen_require(` - type virtd_lxc_t; - ') -') interface(`virt_stub_svirt_sandbox_domain',` gen_require(` attribute svirt_sandbox_domain; diff --git a/contrib/docker-engine-selinux/docker.te b/contrib/docker-engine-selinux/docker.te index dc41f3a960..5adfe23fe9 100644 --- a/contrib/docker-engine-selinux/docker.te +++ b/contrib/docker-engine-selinux/docker.te @@ -90,7 +90,6 @@ files_etc_filetrans(docker_t, docker_config_t, dir, "docker") manage_dirs_pattern(docker_t, docker_lock_t, docker_lock_t) manage_files_pattern(docker_t, docker_lock_t, docker_lock_t) -files_lock_filetrans(docker_t, docker_lock_t, { dir file }, "lxc") manage_dirs_pattern(docker_t, docker_log_t, docker_log_t) manage_files_pattern(docker_t, docker_log_t, docker_log_t) @@ -213,10 +212,6 @@ optional_policy(` openvswitch_stream_connect(docker_t) ') -# -# lxc rules -# - allow docker_t self:capability { dac_override setgid setpcap setuid sys_admin sys_boot sys_chroot sys_ptrace }; allow docker_t self:process { getcap setcap setexec setpgid setsched signal_perms }; @@ -317,7 +312,6 @@ optional_policy(` virt_exec_sandbox_files(docker_t) virt_manage_sandbox_files(docker_t) virt_relabel_sandbox_filesystem(docker_t) - # for lxc virt_transition_svirt_sandbox(docker_t, system_r) virt_mounton_sandbox_file(docker_t) # virt_attach_sandbox_tun_iface(docker_t) @@ -387,11 +381,6 @@ optional_policy(` docker_exec(staff_t) ') -optional_policy(` - virt_stub_lxc() - docker_exec_lib(virtd_lxc_t) -') - optional_policy(` virt_stub_svirt_sandbox_domain() virt_stub_svirt_sandbox_file() diff --git a/contrib/mkseccomp.pl b/contrib/mkseccomp.pl deleted file mode 100755 index 28d0645af0..0000000000 --- a/contrib/mkseccomp.pl +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/perl -# -# A simple helper script to help people build seccomp profiles for -# Docker/LXC. The goal is mostly to reduce the attack surface to the -# kernel, by restricting access to rarely used, recently added or not used -# syscalls. -# -# This script processes one or more files which contain the list of system -# calls to be allowed. See mkseccomp.sample for more information how you -# can configure the list of syscalls. When run, this script produces output -# which, when stored in a file, can be passed to docker as follows: -# -# docker run --lxc-conf="lxc.seccomp=$file" <rest of arguments> -# -# The included sample file shows how to cut about a quarter of all syscalls, -# which affecting most applications. -# -# For specific situations it is possible to reduce the list further. By -# reducing the list to just those syscalls required by a certain application -# you can make it difficult for unknown/unexpected code to run. -# -# Run this script as follows: -# -# ./mkseccomp.pl < mkseccomp.sample >syscalls.list -# or -# ./mkseccomp.pl mkseccomp.sample >syscalls.list -# -# Multiple files can be specified, in which case the lists of syscalls are -# combined. -# -# By Martijn van Oosterhout <kleptog@svana.org> Nov 2013 - -# How it works: -# -# This program basically spawns two processes to form a chain like: -# -# <process data section to prefix __NR_> | cpp | <add header and filter unknown syscalls> - -use strict; -use warnings; - -if( -t ) { - print STDERR "Helper script to make seccomp filters for Docker/LXC.\n"; - print STDERR "Usage: mkseccomp.pl < [files...]\n"; - exit 1; -} - -my $pid = open(my $in, "-|") // die "Couldn't fork1 ($!)\n"; - -if($pid == 0) { # Child - $pid = open(my $out, "|-") // die "Couldn't fork2 ($!)\n"; - - if($pid == 0) { # Child, which execs cpp - exec "cpp" or die "Couldn't exec cpp ($!)\n"; - exit 1; - } - - # Process the DATA section and output to cpp - print $out "#include <sys/syscall.h>\n"; - while(<>) { - if(/^\w/) { - print $out "__NR_$_"; - } - } - close $out; - exit 0; - -} - -# Print header and then process output from cpp. -print "1\n"; -print "whitelist\n"; - -while(<$in>) { - print if( /^[0-9]/ ); -} - diff --git a/contrib/mkseccomp.sample b/contrib/mkseccomp.sample deleted file mode 100644 index a9131e4b1a..0000000000 --- a/contrib/mkseccomp.sample +++ /dev/null @@ -1,444 +0,0 @@ -/* This sample file is an example for mkseccomp.pl to produce a seccomp file - * which restricts syscalls that are only useful for an admin but allows the - * vast majority of normal userspace programs to run normally. - * - * The format of this file is one line per syscall. This is then processed - * and passed to 'cpp' to convert the names to numbers using whatever is - * correct for your platform. As such C-style comments are permitted. Note - * this also means that C preprocessor macros are also allowed. So it is - * possible to create groups surrounded by #ifdef/#endif and control their - * inclusion via #define (not #include). - * - * Syscalls that don't exist on your architecture are silently filtered out. - * Syscalls marked with (*) are required for a container to spawn a bash - * shell successfully (not necessarily full featured). Listing the same - * syscall multiple times is no problem. - * - * If you want to make a list specifically for one application the easiest - * way is to run the application under strace, like so: - * - * $ strace -f -q -c -o strace.out application args... - * - * Once you have a reasonable sample of the execution of the program, exit - * it. The file strace.out will have a summary of the syscalls used. Copy - * that list into this file, comment out everything else except the starred - * syscalls (which you need for the container to start) and you're done. - * - * To get the list of syscalls from the strace output this works well for - * me - * - * $ cut -c52 < strace.out - * - * This sample list was compiled as a combination of all the syscalls - * available on i386 and amd64 on Ubuntu Precise, as such it may not contain - * everything and not everything may be relevant for your system. This - * shouldn't be a problem. - */ - -// Filesystem/File descriptor related -access // (*) -chdir // (*) -chmod -chown -chown32 -close // (*) -creat -dup // (*) -dup2 // (*) -dup3 -epoll_create -epoll_create1 -epoll_ctl -epoll_ctl_old -epoll_pwait -epoll_wait -epoll_wait_old -eventfd -eventfd2 -faccessat // (*) -fadvise64 -fadvise64_64 -fallocate -fanotify_init -fanotify_mark -ioctl // (*) -fchdir -fchmod -fchmodat -fchown -fchown32 -fchownat -fcntl // (*) -fcntl64 -fdatasync -fgetxattr -flistxattr -flock -fremovexattr -fsetxattr -fstat // (*) -fstat64 -fstatat64 -fstatfs -fstatfs64 -fsync -ftruncate -ftruncate64 -getcwd // (*) -getdents // (*) -getdents64 -getxattr -inotify_add_watch -inotify_init -inotify_init1 -inotify_rm_watch -io_cancel -io_destroy -io_getevents -io_setup -io_submit -lchown -lchown32 -lgetxattr -link -linkat -listxattr -llistxattr -llseek -_llseek -lremovexattr -lseek // (*) -lsetxattr -lstat -lstat64 -mkdir -mkdirat -mknod -mknodat -newfstatat -_newselect -oldfstat -oldlstat -oldolduname -oldstat -olduname -oldwait4 -open // (*) -openat // (*) -pipe // (*) -pipe2 -poll -ppoll -pread64 -preadv -futimesat -pselect6 -pwrite64 -pwritev -read // (*) -readahead -readdir -readlink -readlinkat -readv -removexattr -rename -renameat -rmdir -select -sendfile -sendfile64 -setxattr -splice -stat // (*) -stat64 -statfs // (*) -statfs64 -symlink -symlinkat -sync -sync_file_range -sync_file_range2 -syncfs -tee -truncate -truncate64 -umask -unlink -unlinkat -ustat -utime -utimensat -utimes -write // (*) -writev - -// Network related -accept -accept4 -bind // (*) -connect // (*) -getpeername -getsockname // (*) -getsockopt -listen -recv -recvfrom // (*) -recvmmsg -recvmsg -send -sendmmsg -sendmsg -sendto // (*) -setsockopt -shutdown -socket // (*) -socketcall -socketpair -sethostname // (*) - -// Signal related -pause -rt_sigaction // (*) -rt_sigpending -rt_sigprocmask // (*) -rt_sigqueueinfo -rt_sigreturn // (*) -rt_sigsuspend -rt_sigtimedwait -rt_tgsigqueueinfo -sigaction -sigaltstack // (*) -signal -signalfd -signalfd4 -sigpending -sigprocmask -sigreturn -sigsuspend - -// Other needed POSIX -alarm -brk // (*) -clock_adjtime -clock_getres -clock_gettime -clock_nanosleep -//clock_settime -gettimeofday -nanosleep -nice -sysinfo -syslog -time -timer_create -timer_delete -timerfd_create -timerfd_gettime -timerfd_settime -timer_getoverrun -timer_gettime -timer_settime -times -uname // (*) - -// Memory control -madvise -mbind -mincore -mlock -mlockall -mmap // (*) -mmap2 -mprotect // (*) -mremap -msync -munlock -munlockall -munmap // (*) -remap_file_pages -set_mempolicy -vmsplice - -// Process control -capget -capset // (*) -clone // (*) -execve // (*) -exit // (*) -exit_group // (*) -fork -getcpu -getpgid -getpgrp // (*) -getpid // (*) -getppid // (*) -getpriority -getresgid -getresgid32 -getresuid -getresuid32 -getrlimit // (*) -getrusage -getsid -getuid // (*) -getuid32 -getegid // (*) -getegid32 -geteuid // (*) -geteuid32 -getgid // (*) -getgid32 -getgroups -getgroups32 -getitimer -get_mempolicy -kill -//personality -prctl -prlimit64 -sched_getaffinity -sched_getparam -sched_get_priority_max -sched_get_priority_min -sched_getscheduler -sched_rr_get_interval -//sched_setaffinity -//sched_setparam -//sched_setscheduler -sched_yield -setfsgid -setfsgid32 -setfsuid -setfsuid32 -setgid -setgid32 -setgroups -setgroups32 -setitimer -setpgid // (*) -setpriority -setregid -setregid32 -setresgid -setresgid32 -setresuid -setresuid32 -setreuid -setreuid32 -setrlimit -setsid -setuid -setuid32 -ugetrlimit -vfork -wait4 // (*) -waitid -waitpid - -// IPC -ipc -mq_getsetattr -mq_notify -mq_open -mq_timedreceive -mq_timedsend -mq_unlink -msgctl -msgget -msgrcv -msgsnd -semctl -semget -semop -semtimedop -shmat -shmctl -shmdt -shmget - -// Linux specific, mostly needed for thread-related stuff -arch_prctl // (*) -get_robust_list -get_thread_area -gettid -futex // (*) -restart_syscall // (*) -set_robust_list // (*) -set_thread_area -set_tid_address // (*) -tgkill -tkill - -// Admin syscalls, these are blocked -//acct -//adjtimex -//bdflush -//chroot -//create_module -//delete_module -//get_kernel_syms // Obsolete -//idle // Obsolete -//init_module -//ioperm -//iopl -//ioprio_get -//ioprio_set -//kexec_load -//lookup_dcookie // oprofile only? -//migrate_pages // NUMA -//modify_ldt -//mount -//move_pages // NUMA -//name_to_handle_at // NFS server -//nfsservctl // NFS server -//open_by_handle_at // NFS server -//perf_event_open -//pivot_root -//process_vm_readv // For debugger -//process_vm_writev // For debugger -//ptrace // For debugger -//query_module -//quotactl -//reboot -//setdomainname -//setns -//settimeofday -//sgetmask // Obsolete -//ssetmask // Obsolete -//stime -//swapoff -//swapon -//_sysctl -//sysfs -//sys_setaltroot -//umount -//umount2 -//unshare -//uselib -//vhangup -//vm86 -//vm86old - -// Kernel key management -//add_key -//keyctl -//request_key - -// Unimplemented -//afs_syscall -//break -//ftime -//getpmsg -//gtty -//lock -//madvise1 -//mpx -//prof -//profil -//putpmsg -//security -//stty -//tuxcall -//ulimit -//vserver diff --git a/contrib/vagrant-docker/README.md b/contrib/vagrant-docker/README.md index c1ab6e8d46..360bfad34a 100644 --- a/contrib/vagrant-docker/README.md +++ b/contrib/vagrant-docker/README.md @@ -25,7 +25,7 @@ The initial Docker upstart script will not work because it runs on `127.0.0.1`, ``` description "Docker daemon" -start on filesystem and started lxc-net +start on filesystem stop on runlevel [!2345] respawn diff --git a/daemon/config_unix.go b/daemon/config_unix.go index 3ae67cac55..8772aad977 100644 --- a/daemon/config_unix.go +++ b/daemon/config_unix.go @@ -17,8 +17,6 @@ var ( ) // Config defines the configuration of a docker daemon. -// These are the configuration settings that you pass -// to the docker daemon when you launch it with say: `docker daemon -e lxc` type Config struct { CommonConfig diff --git a/daemon/container.go b/daemon/container.go index bc132af2a3..61b739aa42 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -261,7 +261,6 @@ func (container *Container) jsonPath() (string, error) { return container.getRootResourcePath("config.json") } -// This method must be exported to be used from the lxc template // This directory is only usable when the container is running func (container *Container) rootfsPath() string { return container.basefs diff --git a/daemon/container_unix.go b/daemon/container_unix.go index a4b9cd5a6d..4782caedcf 100644 --- a/daemon/container_unix.go +++ b/daemon/container_unix.go @@ -255,12 +255,6 @@ func (daemon *Daemon) populateCommand(c *Container, env []string) error { autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices) - // TODO: this can be removed after lxc-conf is fully deprecated - lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig) - if err != nil { - return err - } - var rlimits []*ulimit.Rlimit ulimits := c.hostConfig.Ulimits @@ -345,7 +339,6 @@ func (daemon *Daemon) populateCommand(c *Container, env []string) error { GIDMapping: gidMap, GroupAdd: c.hostConfig.GroupAdd, Ipc: ipc, - LxcConfig: lxcConfig, Pid: pid, ReadonlyRootfs: c.hostConfig.ReadonlyRootfs, RemappedRoot: remappedRoot, diff --git a/daemon/daemon.go b/daemon/daemon.go index 13e3f33103..cd55cfdbae 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -451,7 +451,6 @@ func (daemon *Daemon) generateNewName(id string) (string, error) { func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) { // Generate default hostname - // FIXME: the lxc template no longer needs to set a default hostname if config.Hostname == "" { config.Hostname = id[:12] } @@ -786,13 +785,6 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo d.containerGraphDB = graph var sysInitPath string - if config.ExecDriver == "lxc" { - initPath, err := configureSysInit(config, rootUID, rootGID) - if err != nil { - return nil, err - } - sysInitPath = initPath - } sysInfo := sysinfo.New(false) // Check if Devices cgroup is mounted, it is hard requirement for container security, diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index cb63cc97e3..42d4a255c0 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -128,10 +128,6 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC return warnings, err } - if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") { - return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name()) - } - // memory subsystem checks and adjustments if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 { return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB") diff --git a/daemon/exec.go b/daemon/exec.go index bf0335ee49..299aaf6082 100644 --- a/daemon/exec.go +++ b/daemon/exec.go @@ -148,11 +148,6 @@ func (d *Daemon) getActiveContainer(name string) (*Container, error) { // ContainerExecCreate sets up an exec in a running container. func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, error) { - // Not all drivers support Exec (LXC for example) - if err := checkExecSupport(d.execDriver.Name()); err != nil { - return "", err - } - container, err := d.getActiveContainer(config.Container) if err != nil { return "", err diff --git a/daemon/exec_freebsd.go b/daemon/exec_freebsd.go deleted file mode 100644 index 6f1e5e3c1d..0000000000 --- a/daemon/exec_freebsd.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build freebsd - -package daemon - -// checkExecSupport returns an error if the exec driver does not support exec, -// or nil if it is supported. -func checkExecSupport(drivername string) error { - return nil -} diff --git a/daemon/exec_linux.go b/daemon/exec_linux.go deleted file mode 100644 index a360326327..0000000000 --- a/daemon/exec_linux.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build linux - -package daemon - -import ( - "strings" - - "github.com/docker/docker/daemon/execdriver/lxc" -) - -// checkExecSupport returns an error if the exec driver does not support exec, -// or nil if it is supported. -func checkExecSupport(drivername string) error { - if strings.HasPrefix(drivername, lxc.DriverName) { - return lxc.ErrExec - } - return nil -} diff --git a/daemon/exec_windows.go b/daemon/exec_windows.go deleted file mode 100644 index d6f244e6d6..0000000000 --- a/daemon/exec_windows.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build windows - -package daemon - -// checkExecSupport returns an error if the exec driver does not support exec, -// or nil if it is supported. -func checkExecSupport(DriverName string) error { - return nil -} diff --git a/daemon/execdriver/driver_unix.go b/daemon/execdriver/driver_unix.go index af06219f03..501778e34b 100644 --- a/daemon/execdriver/driver_unix.go +++ b/daemon/execdriver/driver_unix.go @@ -100,7 +100,6 @@ type Command struct { GIDMapping []idtools.IDMap `json:"gidmapping"` GroupAdd []string `json:"group_add"` Ipc *Ipc `json:"ipc"` - LxcConfig []string `json:"lxc_config"` Pid *Pid `json:"pid"` ReadonlyRootfs bool `json:"readonly_rootfs"` RemappedRoot *User `json:"remap_root"` diff --git a/daemon/execdriver/execdrivers/execdrivers_linux.go b/daemon/execdriver/execdrivers/execdrivers_linux.go index f4785a64f2..2a708a8310 100644 --- a/daemon/execdriver/execdrivers/execdrivers_linux.go +++ b/daemon/execdriver/execdrivers/execdrivers_linux.go @@ -6,24 +6,15 @@ import ( "fmt" "path" - "github.com/Sirupsen/logrus" "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/daemon/execdriver/lxc" "github.com/docker/docker/daemon/execdriver/native" "github.com/docker/docker/pkg/sysinfo" ) // NewDriver returns a new execdriver.Driver from the given name configured with the provided options. func NewDriver(name string, options []string, root, libPath, initPath string, sysInfo *sysinfo.SysInfo) (execdriver.Driver, error) { - switch name { - case "lxc": - // we want to give the lxc driver the full docker root because it needs - // to access and write config and template files in /var/lib/docker/containers/* - // to be backwards compatible - logrus.Warn("LXC built-in support is deprecated.") - return lxc.NewDriver(root, libPath, initPath, sysInfo.AppArmor) - case "native": - return native.NewDriver(path.Join(root, "execdriver", "native"), initPath, options) + if name != "native" { + return nil, fmt.Errorf("unknown exec driver %s", name) } - return nil, fmt.Errorf("unknown exec driver %s", name) + return native.NewDriver(path.Join(root, "execdriver", "native"), initPath, options) } diff --git a/daemon/execdriver/lxc/driver.go b/daemon/execdriver/lxc/driver.go deleted file mode 100644 index 12793bd01f..0000000000 --- a/daemon/execdriver/lxc/driver.go +++ /dev/null @@ -1,906 +0,0 @@ -// +build linux - -package lxc - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "runtime" - "strconv" - "strings" - "sync" - "syscall" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/pkg/stringutils" - sysinfo "github.com/docker/docker/pkg/system" - "github.com/docker/docker/pkg/term" - "github.com/docker/docker/pkg/version" - "github.com/kr/pty" - "github.com/opencontainers/runc/libcontainer" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" - "github.com/opencontainers/runc/libcontainer/system" - "github.com/opencontainers/runc/libcontainer/user" - "github.com/vishvananda/netns" -) - -// DriverName for lxc driver -const DriverName = "lxc" - -// ErrExec defines unsupported error message -var ErrExec = errors.New("Unsupported: Exec is not supported by the lxc driver") - -// Driver contains all information for lxc driver, -// it implements execdriver.Driver -type Driver struct { - root string // root path for the driver to use - libPath string - initPath string - apparmor bool - sharedRoot bool - activeContainers map[string]*activeContainer - machineMemory int64 - sync.Mutex -} - -type activeContainer struct { - container *configs.Config - cmd *exec.Cmd -} - -// NewDriver returns a new lxc driver, called from NewDriver of execdriver -func NewDriver(root, libPath, initPath string, apparmor bool) (*Driver, error) { - if err := os.MkdirAll(root, 0700); err != nil { - return nil, err - } - // setup unconfined symlink - if err := linkLxcStart(root); err != nil { - return nil, err - } - meminfo, err := sysinfo.ReadMemInfo() - if err != nil { - return nil, err - } - return &Driver{ - apparmor: apparmor, - root: root, - libPath: libPath, - initPath: initPath, - sharedRoot: rootIsShared(), - activeContainers: make(map[string]*activeContainer), - machineMemory: meminfo.MemTotal, - }, nil -} - -// Name implements the exec driver Driver interface. -func (d *Driver) Name() string { - version := d.version() - return fmt.Sprintf("%s-%s", DriverName, version) -} - -func setupNetNs(nsPath string) (*os.Process, error) { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - origns, err := netns.Get() - if err != nil { - return nil, err - } - defer origns.Close() - - f, err := os.OpenFile(nsPath, os.O_RDONLY, 0) - if err != nil { - return nil, fmt.Errorf("failed to get network namespace %q: %v", nsPath, err) - } - defer f.Close() - - nsFD := f.Fd() - if err := netns.Set(netns.NsHandle(nsFD)); err != nil { - return nil, fmt.Errorf("failed to set network namespace %q: %v", nsPath, err) - } - defer netns.Set(origns) - - cmd := exec.Command("/bin/sh", "-c", "while true; do sleep 1; done") - if err := cmd.Start(); err != nil { - return nil, fmt.Errorf("failed to start netns process: %v", err) - } - - return cmd.Process, nil -} - -func killNetNsProc(proc *os.Process) { - proc.Kill() - proc.Wait() -} - -// Run implements the exec driver Driver interface, -// it calls 'exec.Cmd' to launch lxc commands to run a container. -func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execdriver.Hooks) (execdriver.ExitStatus, error) { - var ( - term execdriver.Terminal - err error - dataPath = d.containerDir(c.ID) - ) - - if c.Network == nil || (c.Network.NamespacePath == "" && c.Network.ContainerID == "") { - return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("empty namespace path for non-container network") - } - - container, err := d.createContainer(c) - if err != nil { - return execdriver.ExitStatus{ExitCode: -1}, err - } - - if c.ProcessConfig.Tty { - term, err = NewTtyConsole(&c.ProcessConfig, pipes) - } else { - term, err = execdriver.NewStdConsole(&c.ProcessConfig, pipes) - } - if err != nil { - return execdriver.ExitStatus{ExitCode: -1}, err - } - c.ProcessConfig.Terminal = term - - d.Lock() - d.activeContainers[c.ID] = &activeContainer{ - container: container, - cmd: &c.ProcessConfig.Cmd, - } - d.Unlock() - - c.Mounts = append(c.Mounts, execdriver.Mount{ - Source: d.initPath, - Destination: c.InitPath, - Writable: false, - Private: true, - }) - - if err := d.generateEnvConfig(c); err != nil { - return execdriver.ExitStatus{ExitCode: -1}, err - } - configPath, err := d.generateLXCConfig(c) - if err != nil { - return execdriver.ExitStatus{ExitCode: -1}, err - } - params := []string{ - "lxc-start", - "-n", c.ID, - "-f", configPath, - "-q", - } - - // From lxc>=1.1 the default behavior is to daemonize containers after start - lxcVersion := version.Version(d.version()) - if lxcVersion.GreaterThanOrEqualTo(version.Version("1.1")) { - params = append(params, "-F") - } - - proc := &os.Process{} - if c.Network.ContainerID != "" { - params = append(params, - "--share-net", c.Network.ContainerID, - ) - } else { - proc, err = setupNetNs(c.Network.NamespacePath) - if err != nil { - return execdriver.ExitStatus{ExitCode: -1}, err - } - - pidStr := fmt.Sprintf("%d", proc.Pid) - params = append(params, - "--share-net", pidStr) - } - if c.Ipc != nil { - if c.Ipc.ContainerID != "" { - params = append(params, - "--share-ipc", c.Ipc.ContainerID, - ) - } else if c.Ipc.HostIpc { - params = append(params, - "--share-ipc", "1", - ) - } - } - - params = append(params, - "--", - c.InitPath, - ) - - if c.ProcessConfig.User != "" { - params = append(params, "-u", c.ProcessConfig.User) - } - - if c.ProcessConfig.Privileged { - if d.apparmor { - params[0] = path.Join(d.root, "lxc-start-unconfined") - - } - params = append(params, "-privileged") - } - - if c.WorkingDir != "" { - params = append(params, "-w", c.WorkingDir) - } - - params = append(params, "--", c.ProcessConfig.Entrypoint) - params = append(params, c.ProcessConfig.Arguments...) - - if d.sharedRoot { - // lxc-start really needs / to be non-shared, or all kinds of stuff break - // when lxc-start unmount things and those unmounts propagate to the main - // mount namespace. - // What we really want is to clone into a new namespace and then - // mount / MS_REC|MS_SLAVE, but since we can't really clone or fork - // without exec in go we have to do this horrible shell hack... - shellString := - "mount --make-rslave /; exec " + - stringutils.ShellQuoteArguments(params) - - params = []string{ - "unshare", "-m", "--", "/bin/sh", "-c", shellString, - } - } - logrus.Debugf("lxc params %s", params) - var ( - name = params[0] - arg = params[1:] - ) - aname, err := exec.LookPath(name) - if err != nil { - aname = name - } - c.ProcessConfig.Path = aname - c.ProcessConfig.Args = append([]string{name}, arg...) - - if err := createDeviceNodes(c.Rootfs, c.AutoCreatedDevices); err != nil { - killNetNsProc(proc) - return execdriver.ExitStatus{ExitCode: -1}, err - } - - if err := c.ProcessConfig.Start(); err != nil { - killNetNsProc(proc) - return execdriver.ExitStatus{ExitCode: -1}, err - } - - var ( - waitErr error - waitLock = make(chan struct{}) - ) - - go func() { - if err := c.ProcessConfig.Wait(); err != nil { - if _, ok := err.(*exec.ExitError); !ok { // Do not propagate the error if it's simply a status code != 0 - waitErr = err - } - } - close(waitLock) - }() - - terminate := func(terr error) (execdriver.ExitStatus, error) { - if c.ProcessConfig.Process != nil { - c.ProcessConfig.Process.Kill() - c.ProcessConfig.Wait() - } - return execdriver.ExitStatus{ExitCode: -1}, terr - } - // Poll lxc for RUNNING status - pid, err := d.waitForStart(c, waitLock) - if err != nil { - killNetNsProc(proc) - return terminate(err) - } - killNetNsProc(proc) - - cgroupPaths, err := cgroupPaths(c.ID) - if err != nil { - return terminate(err) - } - - state := &libcontainer.State{ - InitProcessPid: pid, - CgroupPaths: cgroupPaths, - } - - f, err := os.Create(filepath.Join(dataPath, "state.json")) - if err != nil { - return terminate(err) - } - defer f.Close() - - if err := json.NewEncoder(f).Encode(state); err != nil { - return terminate(err) - } - - c.ContainerPid = pid - - if hooks.Start != nil { - logrus.Debugf("Invoking startCallback") - chOOM := make(chan struct{}) - close(chOOM) - hooks.Start(&c.ProcessConfig, pid, chOOM) - } - - oomKillNotification := notifyChannelOOM(cgroupPaths) - - <-waitLock - exitCode := getExitCode(c) - - _, oomKill := <-oomKillNotification - logrus.Debugf("oomKill error: %v, waitErr: %v", oomKill, waitErr) - - // check oom error - if oomKill { - exitCode = 137 - } - - return execdriver.ExitStatus{ExitCode: exitCode, OOMKilled: oomKill}, waitErr -} - -func notifyChannelOOM(paths map[string]string) <-chan struct{} { - oom, err := notifyOnOOM(paths) - if err != nil { - logrus.Warnf("Your kernel does not support OOM notifications: %s", err) - c := make(chan struct{}) - close(c) - return c - } - return oom -} - -// copy from libcontainer -func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) { - dir := paths["memory"] - if dir == "" { - return nil, fmt.Errorf("There is no path for %q in state", "memory") - } - oomControl, err := os.Open(filepath.Join(dir, "memory.oom_control")) - if err != nil { - return nil, err - } - fd, _, syserr := syscall.RawSyscall(syscall.SYS_EVENTFD2, 0, syscall.FD_CLOEXEC, 0) - if syserr != 0 { - oomControl.Close() - return nil, syserr - } - - eventfd := os.NewFile(fd, "eventfd") - - eventControlPath := filepath.Join(dir, "cgroup.event_control") - data := fmt.Sprintf("%d %d", eventfd.Fd(), oomControl.Fd()) - if err := ioutil.WriteFile(eventControlPath, []byte(data), 0700); err != nil { - eventfd.Close() - oomControl.Close() - return nil, err - } - ch := make(chan struct{}) - go func() { - defer func() { - close(ch) - eventfd.Close() - oomControl.Close() - }() - buf := make([]byte, 8) - for { - if _, err := eventfd.Read(buf); err != nil { - logrus.Warn(err) - return - } - // When a cgroup is destroyed, an event is sent to eventfd. - // So if the control path is gone, return instead of notifying. - if _, err := os.Lstat(eventControlPath); os.IsNotExist(err) { - logrus.Warn(err) - return - } - ch <- struct{}{} - } - }() - return ch, nil -} - -// createContainer populates and configures the container type with the -// data provided by the execdriver.Command -func (d *Driver) createContainer(c *execdriver.Command) (*configs.Config, error) { - container := execdriver.InitContainer(c) - if err := execdriver.SetupCgroups(container, c); err != nil { - return nil, err - } - return container, nil -} - -// Return an map of susbystem -> absolute container cgroup path -func cgroupPaths(containerID string) (map[string]string, error) { - subsystems, err := cgroups.GetAllSubsystems() - if err != nil { - return nil, err - } - logrus.Debugf("subsystems: %s", subsystems) - paths := make(map[string]string) - for _, subsystem := range subsystems { - cgroupRoot, cgroupDir, err := findCgroupRootAndDir(subsystem) - logrus.Debugf("cgroup path %s %s", cgroupRoot, cgroupDir) - if err != nil { - //unsupported subystem - continue - } - // if we are running dind - dockerPathIdx := strings.LastIndex(cgroupDir, "docker") - if dockerPathIdx != -1 { - cgroupDir = cgroupDir[:dockerPathIdx-1] - } - path := filepath.Join(cgroupRoot, cgroupDir, "lxc", containerID) - paths[subsystem] = path - } - - return paths, nil -} - -// this is copy from old libcontainer nodes.go -func createDeviceNodes(rootfs string, nodesToCreate []*configs.Device) error { - oldMask := syscall.Umask(0000) - defer syscall.Umask(oldMask) - - for _, node := range nodesToCreate { - if err := createDeviceNode(rootfs, node); err != nil { - return err - } - } - return nil -} - -// Creates the device node in the rootfs of the container. -func createDeviceNode(rootfs string, node *configs.Device) error { - var ( - dest = filepath.Join(rootfs, node.Path) - parent = filepath.Dir(dest) - ) - - if err := os.MkdirAll(parent, 0755); err != nil { - return err - } - - fileMode := node.FileMode - switch node.Type { - case 'c': - fileMode |= syscall.S_IFCHR - case 'b': - fileMode |= syscall.S_IFBLK - default: - return fmt.Errorf("%c is not a valid device type for device %s", node.Type, node.Path) - } - - if err := syscall.Mknod(dest, uint32(fileMode), node.Mkdev()); err != nil && !os.IsExist(err) { - return fmt.Errorf("mknod %s %s", node.Path, err) - } - - if err := syscall.Chown(dest, int(node.Uid), int(node.Gid)); err != nil { - return fmt.Errorf("chown %s to %d:%d", node.Path, node.Uid, node.Gid) - } - - return nil -} - -// setupUser changes the groups, gid, and uid for the user inside the container -// copy from libcontainer, cause not it's private -func setupUser(userSpec string) error { - // Set up defaults. - defaultExecUser := user.ExecUser{ - Uid: syscall.Getuid(), - Gid: syscall.Getgid(), - Home: "/", - } - passwdPath, err := user.GetPasswdPath() - if err != nil { - return err - } - groupPath, err := user.GetGroupPath() - if err != nil { - return err - } - execUser, err := user.GetExecUserPath(userSpec, &defaultExecUser, passwdPath, groupPath) - if err != nil { - return err - } - if err := syscall.Setgroups(execUser.Sgids); err != nil { - return err - } - if err := system.Setgid(execUser.Gid); err != nil { - return err - } - if err := system.Setuid(execUser.Uid); err != nil { - return err - } - // if we didn't get HOME already, set it based on the user's HOME - if envHome := os.Getenv("HOME"); envHome == "" { - if err := os.Setenv("HOME", execUser.Home); err != nil { - return err - } - } - return nil -} - -// getExitCode returns the exit code of the process. -// If the process has not exited -1 will be returned. -func getExitCode(c *execdriver.Command) int { - if c.ProcessConfig.ProcessState == nil { - return -1 - } - return c.ProcessConfig.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() -} - -// Kill implements the exec driver Driver interface. -func (d *Driver) Kill(c *execdriver.Command, sig int) error { - if sig == 9 || c.ProcessConfig.Process == nil { - return killLxc(c.ID, sig) - } - - return c.ProcessConfig.Process.Signal(syscall.Signal(sig)) -} - -// Pause implements the exec driver Driver interface, -// it executes lxc-freeze to pause a container. -func (d *Driver) Pause(c *execdriver.Command) error { - _, err := exec.LookPath("lxc-freeze") - if err == nil { - output, errExec := exec.Command("lxc-freeze", "-n", c.ID).CombinedOutput() - if errExec != nil { - return fmt.Errorf("Err: %s Output: %s", errExec, output) - } - } - - return err -} - -// Unpause implements the exec driver Driver interface, -// it executes lxc-unfreeze to unpause a container. -func (d *Driver) Unpause(c *execdriver.Command) error { - _, err := exec.LookPath("lxc-unfreeze") - if err == nil { - output, errExec := exec.Command("lxc-unfreeze", "-n", c.ID).CombinedOutput() - if errExec != nil { - return fmt.Errorf("Err: %s Output: %s", errExec, output) - } - } - - return err -} - -// Terminate implements the exec driver Driver interface. -func (d *Driver) Terminate(c *execdriver.Command) error { - return killLxc(c.ID, 9) -} - -func (d *Driver) version() string { - var ( - version string - output []byte - err error - ) - if _, errPath := exec.LookPath("lxc-version"); errPath == nil { - output, err = exec.Command("lxc-version").CombinedOutput() - } else { - output, err = exec.Command("lxc-start", "--version").CombinedOutput() - } - if err == nil { - version = strings.TrimSpace(string(output)) - if parts := strings.SplitN(version, ":", 2); len(parts) == 2 { - version = strings.TrimSpace(parts[1]) - } - } - return version -} - -func killLxc(id string, sig int) error { - var ( - err error - output []byte - ) - _, err = exec.LookPath("lxc-kill") - if err == nil { - output, err = exec.Command("lxc-kill", "-n", id, strconv.Itoa(sig)).CombinedOutput() - } else { - // lxc-stop does not take arbitrary signals like lxc-kill does - output, err = exec.Command("lxc-stop", "-k", "-n", id).CombinedOutput() - } - if err != nil { - return fmt.Errorf("Err: %s Output: %s", err, output) - } - return nil -} - -// wait for the process to start and return the pid for the process -func (d *Driver) waitForStart(c *execdriver.Command, waitLock chan struct{}) (int, error) { - var ( - err error - output []byte - ) - // We wait for the container to be fully running. - // Timeout after 5 seconds. In case of broken pipe, just retry. - // Note: The container can run and finish correctly before - // the end of this loop - for now := time.Now(); time.Since(now) < 5*time.Second; { - select { - case <-waitLock: - // If the process dies while waiting for it, just return - return -1, nil - default: - } - - output, err = d.getInfo(c.ID) - if err == nil { - info, err := parseLxcInfo(string(output)) - if err != nil { - return -1, err - } - if info.Running { - return info.Pid, nil - } - } - time.Sleep(50 * time.Millisecond) - } - return -1, execdriver.ErrNotRunning -} - -func (d *Driver) getInfo(id string) ([]byte, error) { - return exec.Command("lxc-info", "-n", id).CombinedOutput() -} - -type info struct { - ID string - driver *Driver -} - -func (i *info) IsRunning() bool { - var running bool - - output, err := i.driver.getInfo(i.ID) - if err != nil { - logrus.Errorf("Error getting info for lxc container %s: %s (%s)", i.ID, err, output) - return false - } - if strings.Contains(string(output), "RUNNING") { - running = true - } - return running -} - -// Info implements the exec driver Driver interface. -func (d *Driver) Info(id string) execdriver.Info { - return &info{ - ID: id, - driver: d, - } -} - -func findCgroupRootAndDir(subsystem string) (string, string, error) { - cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem) - if err != nil { - return "", "", err - } - - cgroupDir, err := cgroups.GetThisCgroupDir(subsystem) - if err != nil { - return "", "", err - } - return cgroupRoot, cgroupDir, nil -} - -// GetPidsForContainer implements the exec driver Driver interface. -func (d *Driver) GetPidsForContainer(id string) ([]int, error) { - pids := []int{} - - // cpu is chosen because it is the only non optional subsystem in cgroups - subsystem := "cpu" - cgroupRoot, cgroupDir, err := findCgroupRootAndDir(subsystem) - if err != nil { - return pids, err - } - - filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks") - if _, err := os.Stat(filename); os.IsNotExist(err) { - // With more recent lxc versions use, cgroup will be in lxc/ - filename = filepath.Join(cgroupRoot, cgroupDir, "lxc", id, "tasks") - } - - output, err := ioutil.ReadFile(filename) - if err != nil { - return pids, err - } - for _, p := range strings.Split(string(output), "\n") { - if len(p) == 0 { - continue - } - pid, err := strconv.Atoi(p) - if err != nil { - return pids, fmt.Errorf("Invalid pid '%s': %s", p, err) - } - pids = append(pids, pid) - } - return pids, nil -} - -func linkLxcStart(root string) error { - sourcePath, err := exec.LookPath("lxc-start") - if err != nil { - return err - } - targetPath := path.Join(root, "lxc-start-unconfined") - - if _, err := os.Lstat(targetPath); err != nil && !os.IsNotExist(err) { - return err - } else if err == nil { - if err := os.Remove(targetPath); err != nil { - return err - } - } - return os.Symlink(sourcePath, targetPath) -} - -// TODO: This can be moved to the mountinfo reader in the mount pkg -func rootIsShared() bool { - if data, err := ioutil.ReadFile("/proc/self/mountinfo"); err == nil { - for _, line := range strings.Split(string(data), "\n") { - cols := strings.Split(line, " ") - if len(cols) >= 6 && cols[4] == "/" { - return strings.HasPrefix(cols[6], "shared") - } - } - } - - // No idea, probably safe to assume so - return true -} - -func (d *Driver) containerDir(containerID string) string { - return path.Join(d.libPath, "containers", containerID) -} - -func (d *Driver) generateLXCConfig(c *execdriver.Command) (string, error) { - root := path.Join(d.containerDir(c.ID), "config.lxc") - - fo, err := os.Create(root) - if err != nil { - return "", err - } - defer fo.Close() - - if err := lxcTemplateCompiled.Execute(fo, struct { - *execdriver.Command - AppArmor bool - }{ - Command: c, - AppArmor: d.apparmor, - }); err != nil { - return "", err - } - - return root, nil -} - -func (d *Driver) generateEnvConfig(c *execdriver.Command) error { - data, err := json.Marshal(c.ProcessConfig.Env) - if err != nil { - return err - } - p := path.Join(d.libPath, "containers", c.ID, "config.env") - c.Mounts = append(c.Mounts, execdriver.Mount{ - Source: p, - Destination: "/.dockerenv", - Writable: false, - Private: true, - }) - - return ioutil.WriteFile(p, data, 0600) -} - -// Clean implements the exec driver Driver interface, -// it's not implemented by lxc. -func (d *Driver) Clean(id string) error { - return nil -} - -// TtyConsole implements the exec driver Terminal interface, -// it stores the master and slave ends of the container's pty. -type TtyConsole struct { - MasterPty *os.File - SlavePty *os.File -} - -// NewTtyConsole returns a new TtyConsole struct. -// Wired up to the provided process config and stdin/stdout/stderr pipes. -func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes) (*TtyConsole, error) { - // lxc is special in that we cannot create the master outside of the container without - // opening the slave because we have nothing to provide to the cmd. We have to open both then do - // the crazy setup on command right now instead of passing the console path to lxc and telling it - // to open up that console. we save a couple of openfiles in the native driver because we can do - // this. - ptyMaster, ptySlave, err := pty.Open() - if err != nil { - return nil, err - } - - tty := &TtyConsole{ - MasterPty: ptyMaster, - SlavePty: ptySlave, - } - - if err := tty.AttachPipes(&processConfig.Cmd, pipes); err != nil { - tty.Close() - return nil, err - } - - processConfig.Console = tty.SlavePty.Name() - - return tty, nil -} - -// Resize implements Resize method of Terminal interface -func (t *TtyConsole) Resize(h, w int) error { - return term.SetWinsize(t.MasterPty.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)}) -} - -// AttachPipes attaches given pipes to exec.Cmd -func (t *TtyConsole) AttachPipes(command *exec.Cmd, pipes *execdriver.Pipes) error { - command.Stdout = t.SlavePty - command.Stderr = t.SlavePty - - go func() { - if wb, ok := pipes.Stdout.(interface { - CloseWriters() error - }); ok { - defer wb.CloseWriters() - } - - io.Copy(pipes.Stdout, t.MasterPty) - }() - - if pipes.Stdin != nil { - command.Stdin = t.SlavePty - command.SysProcAttr.Setctty = true - - go func() { - io.Copy(t.MasterPty, pipes.Stdin) - - pipes.Stdin.Close() - }() - } - return nil -} - -// Close implements Close method of Terminal interface -func (t *TtyConsole) Close() error { - t.SlavePty.Close() - return t.MasterPty.Close() -} - -// Exec implements the exec driver Driver interface, -// it is not implemented by lxc. -func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, hooks execdriver.Hooks) (int, error) { - return -1, ErrExec -} - -// Stats implements the exec driver Driver interface. -// Lxc doesn't implement it's own Stats, it does some trick by implementing -// execdriver.Stats to get stats info by libcontainer APIs. -func (d *Driver) Stats(id string) (*execdriver.ResourceStats, error) { - if _, ok := d.activeContainers[id]; !ok { - return nil, fmt.Errorf("%s is not a key in active containers", id) - } - return execdriver.Stats(d.containerDir(id), d.activeContainers[id].container.Cgroups.Memory, d.machineMemory) -} - -// SupportsHooks implements the execdriver Driver interface. -// The LXC execdriver does not support the hook mechanism, which is currently unique to runC/libcontainer. -func (d *Driver) SupportsHooks() bool { - return false -} diff --git a/daemon/execdriver/lxc/info.go b/daemon/execdriver/lxc/info.go deleted file mode 100644 index 3a63091325..0000000000 --- a/daemon/execdriver/lxc/info.go +++ /dev/null @@ -1,53 +0,0 @@ -// +build linux - -package lxc - -import ( - "bufio" - "errors" - "strconv" - "strings" -) - -// Define error messages -var ( - ErrCannotParse = errors.New("cannot parse raw input") -) - -type lxcInfo struct { - Running bool - Pid int -} - -func parseLxcInfo(raw string) (*lxcInfo, error) { - if raw == "" { - return nil, ErrCannotParse - } - var ( - err error - s = bufio.NewScanner(strings.NewReader(raw)) - info = &lxcInfo{} - ) - for s.Scan() { - text := s.Text() - - if s.Err() != nil { - return nil, s.Err() - } - - parts := strings.Split(text, ":") - if len(parts) < 2 { - continue - } - switch strings.ToLower(strings.TrimSpace(parts[0])) { - case "state": - info.Running = strings.TrimSpace(parts[1]) == "RUNNING" - case "pid": - info.Pid, err = strconv.Atoi(strings.TrimSpace(parts[1])) - if err != nil { - return nil, err - } - } - } - return info, nil -} diff --git a/daemon/execdriver/lxc/info_test.go b/daemon/execdriver/lxc/info_test.go deleted file mode 100644 index 996d56b2a3..0000000000 --- a/daemon/execdriver/lxc/info_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build linux - -package lxc - -import ( - "testing" -) - -func TestParseRunningInfo(t *testing.T) { - raw := ` - state: RUNNING - pid: 50` - - info, err := parseLxcInfo(raw) - if err != nil { - t.Fatal(err) - } - if !info.Running { - t.Fatal("info should return a running state") - } - if info.Pid != 50 { - t.Fatalf("info should have pid 50 got %d", info.Pid) - } -} - -func TestEmptyInfo(t *testing.T) { - _, err := parseLxcInfo("") - if err == nil { - t.Fatal("error should not be nil") - } -} - -func TestBadInfo(t *testing.T) { - _, err := parseLxcInfo("state") - if err != nil { - t.Fatal(err) - } -} diff --git a/daemon/execdriver/lxc/init.go b/daemon/execdriver/lxc/init.go deleted file mode 100644 index da5d502088..0000000000 --- a/daemon/execdriver/lxc/init.go +++ /dev/null @@ -1,145 +0,0 @@ -// +build linux - -package lxc - -import ( - "encoding/json" - "flag" - "fmt" - "os" - "os/exec" - "runtime" - "strings" - "syscall" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/pkg/reexec" -) - -// InitArgs contains args provided to the init function for a driver -type InitArgs struct { - User string - Gateway string - IP string - WorkDir string - Privileged bool - Env []string - Args []string - Mtu int - Console string - Pipe int - Root string - CapAdd string - CapDrop string -} - -func init() { - // like always lxc requires a hack to get this to work - reexec.Register("/.dockerinit", dockerInititalizer) -} - -func dockerInititalizer() { - initializer() -} - -// initializer is the lxc driver's init function that is run inside the namespace to setup -// additional configurations -func initializer() { - runtime.LockOSThread() - - args := getArgs() - - if err := setupNamespace(args); err != nil { - logrus.Fatal(err) - } -} - -func setupNamespace(args *InitArgs) error { - if err := setupEnv(args); err != nil { - return err - } - - if err := finalizeNamespace(args); err != nil { - return err - } - - path, err := exec.LookPath(args.Args[0]) - if err != nil { - logrus.Infof("Unable to locate %v", args.Args[0]) - os.Exit(127) - } - - if err := syscall.Exec(path, args.Args, os.Environ()); err != nil { - return fmt.Errorf("dockerinit unable to execute %s - %s", path, err) - } - - return nil -} - -func getArgs() *InitArgs { - var ( - // Get cmdline arguments - user = flag.String("u", "", "username or uid") - gateway = flag.String("g", "", "gateway address") - ip = flag.String("i", "", "ip address") - workDir = flag.String("w", "", "workdir") - privileged = flag.Bool("privileged", false, "privileged mode") - mtu = flag.Int("mtu", 1500, "interface mtu") - capAdd = flag.String("cap-add", "", "capabilities to add") - capDrop = flag.String("cap-drop", "", "capabilities to drop") - ) - - flag.Parse() - - return &InitArgs{ - User: *user, - Gateway: *gateway, - IP: *ip, - WorkDir: *workDir, - Privileged: *privileged, - Args: flag.Args(), - Mtu: *mtu, - CapAdd: *capAdd, - CapDrop: *capDrop, - } -} - -// Clear environment pollution introduced by lxc-start -func setupEnv(args *InitArgs) error { - // Get env - var env []string - dockerenv, err := os.Open(".dockerenv") - if err != nil { - return fmt.Errorf("Unable to load environment variables: %v", err) - } - defer dockerenv.Close() - if err := json.NewDecoder(dockerenv).Decode(&env); err != nil { - return fmt.Errorf("Unable to decode environment variables: %v", err) - } - // Propagate the plugin-specific container env variable - env = append(env, "container="+os.Getenv("container")) - - args.Env = env - - os.Clearenv() - for _, kv := range args.Env { - parts := strings.SplitN(kv, "=", 2) - if len(parts) == 1 { - parts = append(parts, "") - } - os.Setenv(parts[0], parts[1]) - } - - return nil -} - -// Setup working directory -func setupWorkingDirectory(args *InitArgs) error { - if args.WorkDir == "" { - return nil - } - if err := syscall.Chdir(args.WorkDir); err != nil { - return fmt.Errorf("Unable to change dir to %v: %v", args.WorkDir, err) - } - return nil -} diff --git a/daemon/execdriver/lxc/lxc_init_linux.go b/daemon/execdriver/lxc/lxc_init_linux.go deleted file mode 100644 index c63a0cbba0..0000000000 --- a/daemon/execdriver/lxc/lxc_init_linux.go +++ /dev/null @@ -1,22 +0,0 @@ -// +build linux - -package lxc - -import ( - "fmt" - - "github.com/opencontainers/runc/libcontainer/utils" -) - -func finalizeNamespace(args *InitArgs) error { - if err := utils.CloseExecFrom(3); err != nil { - return err - } - if err := setupUser(args.User); err != nil { - return fmt.Errorf("setup user %s", err) - } - if err := setupWorkingDirectory(args); err != nil { - return err - } - return nil -} diff --git a/daemon/execdriver/lxc/lxc_init_unsupported.go b/daemon/execdriver/lxc/lxc_init_unsupported.go deleted file mode 100644 index 77e62ac72d..0000000000 --- a/daemon/execdriver/lxc/lxc_init_unsupported.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !linux - -package lxc - -// InitArgs contains args provided to the init function for a driver -type InitArgs struct { -} - -func finalizeNamespace(args *InitArgs) error { - panic("Not supported on this platform") -} diff --git a/daemon/execdriver/lxc/lxc_template.go b/daemon/execdriver/lxc/lxc_template.go deleted file mode 100644 index 6b7996f04c..0000000000 --- a/daemon/execdriver/lxc/lxc_template.go +++ /dev/null @@ -1,247 +0,0 @@ -// +build linux - -package lxc - -import ( - "fmt" - "os" - "strings" - "text/template" - - "github.com/Sirupsen/logrus" - "github.com/docker/docker/daemon/execdriver" - nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" - "github.com/docker/docker/pkg/stringutils" - "github.com/opencontainers/runc/libcontainer/label" -) - -// LxcTemplate is the template for lxc driver, it's used -// to configure LXC. -const LxcTemplate = ` -lxc.network.type = none -# root filesystem -{{$ROOTFS := .Rootfs}} -lxc.rootfs = {{$ROOTFS}} - -# use a dedicated pts for the container (and limit the number of pseudo terminal -# available) -lxc.pts = 1024 - -# disable the main console -lxc.console = none - -# no controlling tty at all -lxc.tty = 1 - -{{if .ProcessConfig.Privileged}} -lxc.cgroup.devices.allow = a -{{else}} -# no implicit access to devices -lxc.cgroup.devices.deny = a -#Allow the devices passed to us in the AllowedDevices list. -{{range $allowedDevice := .AllowedDevices}} -lxc.cgroup.devices.allow = {{$allowedDevice.CgroupString}} -{{end}} -{{end}} - -# standard mount point -# Use mnt.putold as per https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/986385 -lxc.pivotdir = lxc_putold - -# lxc.autodev is not compatible with lxc --device switch -lxc.autodev = 0 - -# NOTICE: These mounts must be applied within the namespace -{{if .ProcessConfig.Privileged}} -# WARNING: mounting procfs and/or sysfs read-write is a known attack vector. -# See e.g. http://blog.zx2c4.com/749 and https://bit.ly/T9CkqJ -# We mount them read-write here, but later, dockerinit will call the Restrict() function to remount them read-only. -# We cannot mount them directly read-only, because that would prevent loading AppArmor profiles. -lxc.mount.entry = proc {{escapeFstabSpaces $ROOTFS}}/proc proc nosuid,nodev,noexec 0 0 -lxc.mount.entry = sysfs {{escapeFstabSpaces $ROOTFS}}/sys sysfs nosuid,nodev,noexec 0 0 - {{if .AppArmor}} -lxc.aa_profile = unconfined - {{end}} -{{else}} -# In non-privileged mode, lxc will automatically mount /proc and /sys in readonly mode -# for security. See: http://man7.org/linux/man-pages/man5/lxc.container.conf.5.html -lxc.mount.auto = proc sys - {{if .AppArmorProfile}} -lxc.aa_profile = {{.AppArmorProfile}} - {{end}} -{{end}} - -{{if .ProcessConfig.Tty}} -lxc.mount.entry = {{.ProcessConfig.Console}} {{escapeFstabSpaces $ROOTFS}}/dev/console none bind,rw,create=file 0 0 -{{end}} - -lxc.mount.entry = devpts {{escapeFstabSpaces $ROOTFS}}/dev/pts devpts {{formatMountLabel "newinstance,ptmxmode=0666,nosuid,noexec,create=dir" ""}} 0 0 -lxc.mount.entry = shm {{escapeFstabSpaces $ROOTFS}}/dev/shm tmpfs {{formatMountLabel "size=65536k,nosuid,nodev,noexec,create=dir" ""}} 0 0 - -{{range $value := .Mounts}} -{{$createVal := isDirectory $value.Source}} -{{if $value.Writable}} -lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,rw,create={{$createVal}} 0 0 -{{else}} -lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,ro,create={{$createVal}} 0 0 -{{end}} -{{end}} - -# limits -{{if .Resources}} -{{if .Resources.Memory}} -lxc.cgroup.memory.limit_in_bytes = {{.Resources.Memory}} -{{end}} -{{if gt .Resources.MemorySwap 0}} -lxc.cgroup.memory.memsw.limit_in_bytes = {{.Resources.MemorySwap}} -{{end}} -{{if gt .Resources.MemoryReservation 0}} -lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.MemoryReservation}} -{{end}} -{{if gt .Resources.KernelMemory 0}} -lxc.cgroup.memory.kmem.limit_in_bytes = {{.Resources.KernelMemory}} -{{end}} -{{if .Resources.CPUShares}} -lxc.cgroup.cpu.shares = {{.Resources.CPUShares}} -{{end}} -{{if .Resources.CPUPeriod}} -lxc.cgroup.cpu.cfs_period_us = {{.Resources.CPUPeriod}} -{{end}} -{{if .Resources.CpusetCpus}} -lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}} -{{end}} -{{if .Resources.CpusetMems}} -lxc.cgroup.cpuset.mems = {{.Resources.CpusetMems}} -{{end}} -{{if .Resources.CPUQuota}} -lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CPUQuota}} -{{end}} -{{if .Resources.BlkioWeight}} -lxc.cgroup.blkio.weight = {{.Resources.BlkioWeight}} -{{end}} -{{if .Resources.OomKillDisable}} -lxc.cgroup.memory.oom_control = {{.Resources.OomKillDisable}} -{{end}} -{{if gt .Resources.MemorySwappiness 0}} -lxc.cgroup.memory.swappiness = {{.Resources.MemorySwappiness}} -{{end}} -{{end}} - -{{if .LxcConfig}} -{{range $value := .LxcConfig}} -lxc.{{$value}} -{{end}} -{{end}} - -{{if .ProcessConfig.Env}} -lxc.utsname = {{getHostname .ProcessConfig.Env}} -{{end}} - -{{if .ProcessConfig.Privileged}} -# No cap values are needed, as lxc is starting in privileged mode -{{else}} - {{ with keepCapabilities .CapAdd .CapDrop }} - {{range .}} -lxc.cap.keep = {{.}} - {{end}} - {{else}} - {{ with dropList .CapDrop }} - {{range .}} -lxc.cap.drop = {{.}} - {{end}} - {{end}} - {{end}} -{{end}} -` - -var lxcTemplateCompiled *template.Template - -// Escape spaces in strings according to the fstab documentation, which is the -// format for "lxc.mount.entry" lines in lxc.conf. See also "man 5 fstab". -func escapeFstabSpaces(field string) string { - return strings.Replace(field, " ", "\\040", -1) -} - -func keepCapabilities(adds []string, drops []string) ([]string, error) { - container := nativeTemplate.New() - logrus.Debugf("adds %s drops %s\n", adds, drops) - caps, err := execdriver.TweakCapabilities(container.Capabilities, adds, drops) - if err != nil { - return nil, err - } - var newCaps []string - for _, cap := range caps { - logrus.Debugf("cap %s\n", cap) - realCap := execdriver.GetCapability(cap) - numCap := fmt.Sprintf("%d", realCap.Value) - newCaps = append(newCaps, numCap) - } - - return newCaps, nil -} - -func dropList(drops []string) ([]string, error) { - if stringutils.InSlice(drops, "all") { - var newCaps []string - for _, capName := range execdriver.GetAllCapabilities() { - cap := execdriver.GetCapability(capName) - logrus.Debugf("drop cap %s\n", cap.Key) - numCap := fmt.Sprintf("%d", cap.Value) - newCaps = append(newCaps, numCap) - } - return newCaps, nil - } - return []string{}, nil -} - -func isDirectory(source string) string { - f, err := os.Stat(source) - logrus.Debugf("dir: %s\n", source) - if err != nil { - if os.IsNotExist(err) { - return "dir" - } - return "" - } - if f.IsDir() { - return "dir" - } - return "file" -} - -func getLabel(c map[string][]string, name string) string { - label := c["label"] - for _, l := range label { - parts := strings.SplitN(l, "=", 2) - if strings.TrimSpace(parts[0]) == name { - return strings.TrimSpace(parts[1]) - } - } - return "" -} - -func getHostname(env []string) string { - for _, kv := range env { - parts := strings.SplitN(kv, "=", 2) - if parts[0] == "HOSTNAME" && len(parts) == 2 { - return parts[1] - } - } - return "" -} - -func init() { - var err error - funcMap := template.FuncMap{ - "escapeFstabSpaces": escapeFstabSpaces, - "formatMountLabel": label.FormatMountLabel, - "isDirectory": isDirectory, - "keepCapabilities": keepCapabilities, - "dropList": dropList, - "getHostname": getHostname, - } - lxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate) - if err != nil { - panic(err) - } -} diff --git a/daemon/execdriver/lxc/lxc_template_unit_test.go b/daemon/execdriver/lxc/lxc_template_unit_test.go deleted file mode 100644 index 8f4065982a..0000000000 --- a/daemon/execdriver/lxc/lxc_template_unit_test.go +++ /dev/null @@ -1,355 +0,0 @@ -// +build linux - -package lxc - -import ( - "bufio" - "fmt" - "io/ioutil" - "math/rand" - "os" - "path" - "strings" - "testing" - "time" - - "github.com/docker/docker/daemon/execdriver" - nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" - "github.com/opencontainers/runc/libcontainer/configs" - "github.com/syndtr/gocapability/capability" -) - -func TestLXCConfig(t *testing.T) { - root, err := ioutil.TempDir("", "TestLXCConfig") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(root) - - os.MkdirAll(path.Join(root, "containers", "1"), 0777) - - // Memory is allocated randomly for testing - r := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) - var ( - memMin = 33554432 - memMax = 536870912 - mem = memMin + r.Intn(memMax-memMin) - swap = memMax - cpuMin = 100 - cpuMax = 10000 - cpu = cpuMin + r.Intn(cpuMax-cpuMin) - ) - - driver, err := NewDriver(root, root, "", false) - if err != nil { - t.Fatal(err) - } - command := &execdriver.Command{ - CommonCommand: execdriver.CommonCommand{ - ID: "1", - Network: &execdriver.Network{ - Mtu: 1500, - }, - ProcessConfig: execdriver.ProcessConfig{}, - Resources: &execdriver.Resources{ - MemorySwap: int64(swap), - CommonResources: execdriver.CommonResources{ - Memory: int64(mem), - CPUShares: int64(cpu), - }, - }, - }, - AllowedDevices: make([]*configs.Device, 0), - } - p, err := driver.generateLXCConfig(command) - if err != nil { - t.Fatal(err) - } - grepFile(t, p, - fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem)) - - grepFile(t, p, - fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", swap)) -} - -func TestCustomLxcConfig(t *testing.T) { - root, err := ioutil.TempDir("", "TestCustomLxcConfig") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(root) - - os.MkdirAll(path.Join(root, "containers", "1"), 0777) - - driver, err := NewDriver(root, root, "", false) - if err != nil { - t.Fatal(err) - } - processConfig := execdriver.ProcessConfig{ - Privileged: false, - } - command := &execdriver.Command{ - CommonCommand: execdriver.CommonCommand{ - ID: "1", - Network: &execdriver.Network{ - Mtu: 1500, - }, - ProcessConfig: processConfig, - }, - LxcConfig: []string{ - "lxc.utsname = docker", - "lxc.cgroup.cpuset.cpus = 0,1", - }, - } - - p, err := driver.generateLXCConfig(command) - if err != nil { - t.Fatal(err) - } - - grepFile(t, p, "lxc.utsname = docker") - grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") -} - -func grepFile(t *testing.T, path string, pattern string) { - grepFileWithReverse(t, path, pattern, false) -} - -func grepFileWithReverse(t *testing.T, path string, pattern string, inverseGrep bool) { - f, err := os.Open(path) - if err != nil { - t.Fatal(err) - } - defer f.Close() - r := bufio.NewReader(f) - var ( - line string - ) - err = nil - for err == nil { - line, err = r.ReadString('\n') - if strings.Contains(line, pattern) == true { - if inverseGrep { - t.Fatalf("grepFile: pattern \"%s\" found in \"%s\"", pattern, path) - } - return - } - } - if inverseGrep { - return - } - t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path) -} - -func TestEscapeFstabSpaces(t *testing.T) { - var testInputs = map[string]string{ - " ": "\\040", - "": "", - "/double space": "/double\\040\\040space", - "/some long test string": "/some\\040long\\040test\\040string", - "/var/lib/docker": "/var/lib/docker", - " leading": "\\040leading", - "trailing ": "trailing\\040", - } - for in, exp := range testInputs { - if out := escapeFstabSpaces(in); exp != out { - t.Logf("Expected %s got %s", exp, out) - t.Fail() - } - } -} - -func TestIsDirectory(t *testing.T) { - tempDir, err := ioutil.TempDir("", "TestIsDir") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - - tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile") - if err != nil { - t.Fatal(err) - } - - if isDirectory(tempDir) != "dir" { - t.Logf("Could not identify %s as a directory", tempDir) - t.Fail() - } - - if isDirectory(tempFile.Name()) != "file" { - t.Logf("Could not identify %s as a file", tempFile.Name()) - t.Fail() - } -} - -func TestCustomLxcConfigMounts(t *testing.T) { - root, err := ioutil.TempDir("", "TestCustomLxcConfig") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(root) - tempDir, err := ioutil.TempDir("", "TestIsDir") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - - tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile") - if err != nil { - t.Fatal(err) - } - os.MkdirAll(path.Join(root, "containers", "1"), 0777) - - driver, err := NewDriver(root, root, "", false) - if err != nil { - t.Fatal(err) - } - processConfig := execdriver.ProcessConfig{ - Privileged: false, - } - mounts := []execdriver.Mount{ - { - Source: tempDir, - Destination: tempDir, - Writable: false, - Private: true, - }, - { - Source: tempFile.Name(), - Destination: tempFile.Name(), - Writable: true, - Private: true, - }, - } - command := &execdriver.Command{ - CommonCommand: execdriver.CommonCommand{ - ID: "1", - Network: &execdriver.Network{ - Mtu: 1500, - }, - Mounts: mounts, - ProcessConfig: processConfig, - }, - LxcConfig: []string{ - "lxc.utsname = docker", - "lxc.cgroup.cpuset.cpus = 0,1", - }, - } - - p, err := driver.generateLXCConfig(command) - if err != nil { - t.Fatal(err) - } - - grepFile(t, p, "lxc.utsname = docker") - grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") - - grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,ro,create=%s 0 0", tempDir, "/"+tempDir, "dir")) - grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,rw,create=%s 0 0", tempFile.Name(), "/"+tempFile.Name(), "file")) -} - -func TestCustomLxcConfigMisc(t *testing.T) { - root, err := ioutil.TempDir("", "TestCustomLxcConfig") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(root) - os.MkdirAll(path.Join(root, "containers", "1"), 0777) - driver, err := NewDriver(root, root, "", true) - - if err != nil { - t.Fatal(err) - } - processConfig := execdriver.ProcessConfig{ - Privileged: false, - } - - processConfig.Env = []string{"HOSTNAME=testhost"} - command := &execdriver.Command{ - CommonCommand: execdriver.CommonCommand{ - ID: "1", - Network: &execdriver.Network{ - Mtu: 1500, - }, - ProcessConfig: processConfig, - }, - LxcConfig: []string{ - "lxc.cgroup.cpuset.cpus = 0,1", - }, - CapAdd: []string{"net_admin", "syslog"}, - CapDrop: []string{"kill", "mknod"}, - AppArmorProfile: "lxc-container-default-with-nesting", - } - - p, err := driver.generateLXCConfig(command) - if err != nil { - t.Fatal(err) - } - grepFile(t, p, "lxc.aa_profile = lxc-container-default-with-nesting") - // hostname - grepFile(t, p, "lxc.utsname = testhost") - grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") - container := nativeTemplate.New() - for _, cap := range container.Capabilities { - realCap := execdriver.GetCapability(cap) - numCap := fmt.Sprintf("%d", realCap.Value) - if cap != "MKNOD" && cap != "KILL" { - grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) - } - } - - grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) - grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) -} - -func TestCustomLxcConfigMiscOverride(t *testing.T) { - root, err := ioutil.TempDir("", "TestCustomLxcConfig") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(root) - os.MkdirAll(path.Join(root, "containers", "1"), 0777) - driver, err := NewDriver(root, root, "", false) - if err != nil { - t.Fatal(err) - } - processConfig := execdriver.ProcessConfig{ - Privileged: false, - } - - processConfig.Env = []string{"HOSTNAME=testhost"} - command := &execdriver.Command{ - CommonCommand: execdriver.CommonCommand{ - ID: "1", - Network: &execdriver.Network{ - Mtu: 1500, - }, - ProcessConfig: processConfig, - }, - LxcConfig: []string{ - "lxc.cgroup.cpuset.cpus = 0,1", - "lxc.network.ipv4 = 172.0.0.1", - }, - CapAdd: []string{"NET_ADMIN", "SYSLOG"}, - CapDrop: []string{"KILL", "MKNOD"}, - } - - p, err := driver.generateLXCConfig(command) - if err != nil { - t.Fatal(err) - } - - // hostname - grepFile(t, p, "lxc.utsname = testhost") - grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") - container := nativeTemplate.New() - for _, cap := range container.Capabilities { - realCap := execdriver.GetCapability(cap) - numCap := fmt.Sprintf("%d", realCap.Value) - if cap != "MKNOD" && cap != "KILL" { - grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) - } - } - grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) - grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) -} diff --git a/daemon/graphdriver/devmapper/deviceset.go b/daemon/graphdriver/devmapper/deviceset.go index 06933aec83..a9b1501870 100644 --- a/daemon/graphdriver/devmapper/deviceset.go +++ b/daemon/graphdriver/devmapper/deviceset.go @@ -1504,7 +1504,7 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error { } // It seems libdevmapper opens this without O_CLOEXEC, and go exec will not close files - // that are not Close-on-exec, and lxc-start will die if it inherits any unexpected files, + // that are not Close-on-exec, // so we add this badhack to make sure it closes itself setCloseOnExec("/dev/mapper/control") diff --git a/daemon/utils_freebsd.go b/daemon/utils_freebsd.go deleted file mode 100644 index 1e1ed1b358..0000000000 --- a/daemon/utils_freebsd.go +++ /dev/null @@ -1,9 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/runconfig" -) - -func mergeLxcConfIntoOptions(hostConfig *runconfig.HostConfig) ([]string, error) { - return nil, nil -} diff --git a/daemon/utils_linux.go b/daemon/utils_linux.go index 042544e43a..83a3447111 100644 --- a/daemon/utils_linux.go +++ b/daemon/utils_linux.go @@ -2,14 +2,7 @@ package daemon -import ( - "errors" - "fmt" - "strings" - - "github.com/docker/docker/runconfig" - "github.com/opencontainers/runc/libcontainer/selinux" -) +import "github.com/opencontainers/runc/libcontainer/selinux" func selinuxSetDisabled() { selinux.SetDisabled() @@ -22,27 +15,3 @@ func selinuxFreeLxcContexts(label string) { func selinuxEnabled() bool { return selinux.SelinuxEnabled() } - -func mergeLxcConfIntoOptions(hostConfig *runconfig.HostConfig) ([]string, error) { - if hostConfig == nil { - return nil, nil - } - - out := []string{} - - // merge in the lxc conf options into the generic config map - if lxcConf := hostConfig.LxcConf; lxcConf != nil { - lxSlice := lxcConf.Slice() - for _, pair := range lxSlice { - // because lxc conf gets the driver name lxc.XXXX we need to trim it off - // and let the lxc driver add it back later if needed - if !strings.Contains(pair.Key, ".") { - return nil, errors.New("Illegal Key passed into LXC Configurations") - } - parts := strings.SplitN(pair.Key, ".", 2) - out = append(out, fmt.Sprintf("%s=%s", parts[1], pair.Value)) - } - } - - return out, nil -} diff --git a/daemon/utils_test.go b/daemon/utils_test.go deleted file mode 100644 index 99165f7810..0000000000 --- a/daemon/utils_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build linux - -package daemon - -import ( - "testing" - - "github.com/docker/docker/runconfig" -) - -func TestMergeLxcConfig(t *testing.T) { - kv := []runconfig.KeyValuePair{ - {"lxc.cgroups.cpuset", "1,2"}, - } - hostConfig := &runconfig.HostConfig{ - LxcConf: runconfig.NewLxcConfig(kv), - } - - out, err := mergeLxcConfIntoOptions(hostConfig) - if err != nil { - t.Fatalf("Failed to merge Lxc Config: %s", err) - } - - cpuset := out[0] - if expected := "cgroups.cpuset=1,2"; cpuset != expected { - t.Fatalf("expected %s got %s", expected, cpuset) - } -} diff --git a/docker/daemon_linux.go b/docker/daemon_linux.go index 4f4e172c6e..0a02128d07 100644 --- a/docker/daemon_linux.go +++ b/docker/daemon_linux.go @@ -4,7 +4,6 @@ package main import ( systemdDaemon "github.com/coreos/go-systemd/daemon" - _ "github.com/docker/docker/daemon/execdriver/lxc" ) // notifySystem sends a message to the host when the server is ready to be used diff --git a/dockerinit/dockerinit.go b/dockerinit/dockerinit.go index a6754b05a1..8a0be56884 100644 --- a/dockerinit/dockerinit.go +++ b/dockerinit/dockerinit.go @@ -1,7 +1,6 @@ package main import ( - _ "github.com/docker/docker/daemon/execdriver/lxc" _ "github.com/docker/docker/daemon/execdriver/native" "github.com/docker/docker/pkg/reexec" ) diff --git a/docs/articles/dockerfile_best-practices.md b/docs/articles/dockerfile_best-practices.md index ea15a14635..5fa7fa4bbe 100644 --- a/docs/articles/dockerfile_best-practices.md +++ b/docs/articles/dockerfile_best-practices.md @@ -212,7 +212,6 @@ recommendations. dpkg-sig \ libcap-dev \ libsqlite3-dev \ - lxc=1.0* \ mercurial \ reprepro \ ruby1.9.1 \ diff --git a/docs/installation/archlinux.md b/docs/installation/archlinux.md index 509742a5d4..103dfd995f 100644 --- a/docs/installation/archlinux.md +++ b/docs/installation/archlinux.md @@ -29,7 +29,6 @@ in the packages. The core dependencies are: - bridge-utils - device-mapper - iproute2 - - lxc - sqlite ## Installation diff --git a/docs/installation/gentoolinux.md b/docs/installation/gentoolinux.md index 6e2ef3f70e..36320d0acc 100644 --- a/docs/installation/gentoolinux.md +++ b/docs/installation/gentoolinux.md @@ -50,7 +50,6 @@ IRC channel on the Freenode network. | contrib | Yes |Install additional contributed scripts and components.| | device-mapper | Yes |Enables dependencies for the "devicemapper" graph driver, including necessary kernel flags.| | doc | |Add extra documentation (API, Javadoc, etc). It is recommended to enable per package instead of globally.| -| lxc | |Enables dependencies for the "lxc" execution driver.| | vim-syntax | |Pulls in related vim syntax scripts.| | zsh-completion| |Enable zsh completion support.| diff --git a/docs/reference/api/docker_remote_api_v1.22.md b/docs/reference/api/docker_remote_api_v1.22.md index 43c6fa98d9..f1a076f09d 100644 --- a/docs/reference/api/docker_remote_api_v1.22.md +++ b/docs/reference/api/docker_remote_api_v1.22.md @@ -174,7 +174,6 @@ Create a container "HostConfig": { "Binds": ["/tmp:/tmp"], "Links": ["redis3:redis"], - "LxcConf": {"lxc.utsname":"docker"}, "Memory": 0, "MemorySwap": 0, "MemoryReservation": 0, @@ -270,8 +269,6 @@ Json Parameters: + `volume_name:container_path:ro` to make the bind mount read-only inside the container. - **Links** - A list of links for the container. Each link entry should be in the form of `container_name:alias`. - - **LxcConf** - LXC specific configurations. These configurations only - work when using the `lxc` execution driver. - **PortBindings** - A map of exposed container ports and the host port they should map to. A JSON object in the form `{ <port>/<protocol>: [{ "HostPort": "<port>" }] }` diff --git a/docs/reference/commandline/create.md b/docs/reference/commandline/create.md index 723bc90a0a..2f11bfbd4d 100644 --- a/docs/reference/commandline/create.md +++ b/docs/reference/commandline/create.md @@ -48,7 +48,6 @@ Creates a new container. --link=[] Add link to another container --log-driver="" Logging driver for container --log-opt=[] Log driver specific options - --lxc-conf=[] Add custom lxc options -m, --memory="" Memory limit --mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33) --memory-reservation="" Memory soft limit diff --git a/docs/reference/commandline/daemon.md b/docs/reference/commandline/daemon.md index 91fd3c6cf0..6da89e6b49 100644 --- a/docs/reference/commandline/daemon.md +++ b/docs/reference/commandline/daemon.md @@ -439,11 +439,6 @@ Currently supported options of `zfs`: The Docker daemon uses a specifically built `libcontainer` execution driver as its interface to the Linux kernel `namespaces`, `cgroups`, and `SELinux`. -There is still legacy support for the original [LXC userspace tools]( -https://linuxcontainers.org/) via the `lxc` execution driver, however, this is -not where the primary development of new functionality is taking place. -Add `-e lxc` to the daemon flags to use the `lxc` execution driver. - ## Options for the native execdriver You can configure the `native` (libcontainer) execdriver using options specified diff --git a/docs/reference/commandline/run.md b/docs/reference/commandline/run.md index 5e7dd5dd9e..76446ca84b 100644 --- a/docs/reference/commandline/run.md +++ b/docs/reference/commandline/run.md @@ -47,7 +47,6 @@ parent = "smn_cli" --link=[] Add link to another container --log-driver="" Logging driver for container --log-opt=[] Log driver specific options - --lxc-conf=[] Add custom lxc options -m, --memory="" Memory limit --mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33) --memory-reservation="" Memory soft limit diff --git a/docs/reference/run.md b/docs/reference/run.md index 1693e52cc7..898a67f8bb 100644 --- a/docs/reference/run.md +++ b/docs/reference/run.md @@ -39,7 +39,6 @@ defaults related to: * container identification * network settings * runtime constraints on CPU and memory - * privileges and LXC configuration With the `docker run [OPTIONS]` an operator can add to or override the image defaults set by a developer. And, additionally, operators can @@ -75,7 +74,7 @@ following options. - [Restart policies (--restart)](#restart-policies-restart) - [Clean up (--rm)](#clean-up-rm) - [Runtime constraints on resources](#runtime-constraints-on-resources) - - [Runtime privilege, Linux capabilities, and LXC configuration](#runtime-privilege-linux-capabilities-and-lxc-configuration) + - [Runtime privilege and Linux capabilities](#runtime-privilege-and-linux-capabilities) ## Detached vs foreground @@ -933,21 +932,18 @@ one can use this flag: $ docker run -ti --rm --group-add audio --group-add dbus --group-add 777 busybox id uid=0(root) gid=0(root) groups=10(wheel),29(audio),81(dbus),777 -## Runtime privilege, Linux capabilities, and LXC configuration +## Runtime privilege and Linux capabilities --cap-add: Add Linux capabilities --cap-drop: Drop Linux capabilities --privileged=false: Give extended privileges to this container --device=[]: Allows you to run devices inside the container without the --privileged flag. - --lxc-conf=[]: Add custom lxc options By default, Docker containers are "unprivileged" and cannot, for example, run a Docker daemon inside a Docker container. This is because by default a container is not allowed to access any devices, but a -"privileged" container is given access to all devices (see [lxc-template.go]( -https://github.com/docker/docker/blob/master/daemon/execdriver/lxc/lxc_template.go) -and documentation on [cgroups devices]( -https://www.kernel.org/doc/Documentation/cgroups/devices.txt)). +"privileged" container is given access to all devices (see +the documentation on [cgroups devices](https://www.kernel.org/doc/Documentation/cgroups/devices.txt)). When the operator executes `docker run --privileged`, Docker will enable to access to all devices on the host as well as set some configuration @@ -1061,22 +1057,6 @@ To mount a FUSE based filesystem, you need to combine both `--cap-add` and .... -If the Docker daemon was started using the `lxc` exec-driver -(`docker daemon --exec-driver=lxc`) then the operator can also specify LXC options -using one or more `--lxc-conf` parameters. These can be new parameters or -override existing parameters from the [lxc-template.go]( -https://github.com/docker/docker/blob/master/daemon/execdriver/lxc/lxc_template.go). -Note that in the future, a given host's docker daemon may not use LXC, so this -is an implementation-specific configuration meant for operators already -familiar with using LXC directly. - -> **Note:** -> If you use `--lxc-conf` to modify a container's configuration which is also -> managed by the Docker daemon, then the Docker daemon will not know about this -> modification, and you will need to manage any conflicts yourself. For example, -> you can use `--lxc-conf` to set a container's IP address, but this will not be -> reflected in the `/etc/hosts` file. - ## Logging drivers (--log-driver) The container can have a different logging driver than the Docker daemon. Use @@ -1258,7 +1238,6 @@ above, or already defined by the developer with a Dockerfile `ENV`: declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" declare -x PWD="/" declare -x SHLVL="1" - declare -x container="lxc" declare -x deep="purple" Similarly the operator can set the **hostname** with `-h`. diff --git a/experimental/userns.md b/experimental/userns.md index 79e06ee4a9..5a204fa7cf 100644 --- a/experimental/userns.md +++ b/experimental/userns.md @@ -109,7 +109,6 @@ running a Docker daemon with experimental user namespaces enabled: - A `--readonly` container filesystem (a Linux kernel restriction on remount with new flags of a currently mounted filesystem when inside a user namespace) - external (volume/graph) drivers which are unaware/incapable of using daemon user mappings - Using `--privileged` mode containers - - Using the lxc execdriver (only the `native` execdriver is enabled to use user namespaces) - volume use without pre-arranging proper file ownership in mounted volumes Additionally, while the `root` user inside a user namespaced container diff --git a/hack/dind b/hack/dind index e4eb53580c..a8c09283f6 100755 --- a/hack/dind +++ b/hack/dind @@ -31,13 +31,6 @@ if ! mountpoint -q /sys/fs/cgroup; then # Mount the cgroup hierarchies exactly as they are in the parent system. for HIER in $(cut -d: -f2 /proc/1/cgroup); do - # The following sections address a bug which manifests itself - # by a cryptic "lxc-start: no ns_cgroup option specified" when - # trying to start containers within a container. - # The bug seems to appear when the cgroup hierarchies are not - # mounted on the exact same directories in the host, and in the - # container. - SUBSYSTEMS="${HIER%name=*}" # If cgroup hierarchy is named(mounted with "-o name=foo") we diff --git a/hack/make.sh b/hack/make.sh index c7318953b4..64f02ea5a5 100755 --- a/hack/make.sh +++ b/hack/make.sh @@ -109,10 +109,6 @@ if [ -z "$DOCKER_CLIENTONLY" ]; then fi fi -if [ "$DOCKER_EXECDRIVER" = 'lxc' ]; then - DOCKER_BUILDTAGS+=' test_no_exec' -fi - # test whether "btrfs/version.h" exists and apply btrfs_noversion appropriately if \ command -v gcc &> /dev/null \ diff --git a/integration-cli/docker_cli_diff_test.go b/integration-cli/docker_cli_diff_test.go index 52209e602b..4f29d36975 100644 --- a/integration-cli/docker_cli_diff_test.go +++ b/integration-cli/docker_cli_diff_test.go @@ -58,8 +58,8 @@ func (s *DockerSuite) TestDiffEnsureOnlyKmsgAndPtmx(c *check.C) { "C /dev": true, "A /dev/full": true, // busybox "C /dev/ptmx": true, // libcontainer - "A /dev/mqueue": true, // lxc - "A /dev/kmsg": true, // lxc + "A /dev/mqueue": true, + "A /dev/kmsg": true, "A /dev/fd": true, "A /dev/fuse": true, "A /dev/ptmx": true, diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 4d89b2f86c..d9fe01ba4c 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -66,13 +66,11 @@ func (s *DockerSuite) TestRunLookupGoogleDns(c *check.C) { } // the exit code should be 0 -// some versions of lxc might make this test fail func (s *DockerSuite) TestRunExitCodeZero(c *check.C) { dockerCmd(c, "run", "busybox", "true") } // the exit code should be 1 -// some versions of lxc might make this test fail func (s *DockerSuite) TestRunExitCodeOne(c *check.C) { _, exitCode, err := dockerCmdWithError("run", "busybox", "false") if err != nil && !strings.Contains("exit status 1", fmt.Sprintf("%s", err)) { @@ -84,7 +82,6 @@ func (s *DockerSuite) TestRunExitCodeOne(c *check.C) { } // it should be possible to pipe in data via stdin to a process running in a container -// some versions of lxc might make this test fail func (s *DockerSuite) TestRunStdinPipe(c *check.C) { // TODO Windows: This needs some work to make compatible. testRequires(c, DaemonIsLinux) @@ -664,7 +661,7 @@ func (s *DockerSuite) TestRunTwoConcurrentContainers(c *check.C) { func (s *DockerSuite) TestRunEnvironment(c *check.C) { // TODO Windows: Environment handling is different between Linux and - // Windows and this test relies currently on lxc and unix functionality. + // Windows and this test relies currently on unix functionality. testRequires(c, DaemonIsLinux) cmd := exec.Command(dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "-e=HOME=", "busybox", "env") cmd.Env = append(os.Environ(), @@ -677,13 +674,7 @@ func (s *DockerSuite) TestRunEnvironment(c *check.C) { c.Fatal(err, out) } - actualEnvLxc := strings.Split(strings.TrimSpace(out), "\n") - actualEnv := []string{} - for i := range actualEnvLxc { - if actualEnvLxc[i] != "container=lxc" { - actualEnv = append(actualEnv, actualEnvLxc[i]) - } - } + actualEnv := strings.Split(strings.TrimSpace(out), "\n") sort.Strings(actualEnv) goodEnv := []string{ @@ -709,7 +700,7 @@ func (s *DockerSuite) TestRunEnvironment(c *check.C) { func (s *DockerSuite) TestRunEnvironmentErase(c *check.C) { // TODO Windows: Environment handling is different between Linux and - // Windows and this test relies currently on lxc and unix functionality. + // Windows and this test relies currently on unix functionality. testRequires(c, DaemonIsLinux) // Test to make sure that when we use -e on env vars that are @@ -724,13 +715,7 @@ func (s *DockerSuite) TestRunEnvironmentErase(c *check.C) { c.Fatal(err, out) } - actualEnvLxc := strings.Split(strings.TrimSpace(out), "\n") - actualEnv := []string{} - for i := range actualEnvLxc { - if actualEnvLxc[i] != "container=lxc" { - actualEnv = append(actualEnv, actualEnvLxc[i]) - } - } + actualEnv := strings.Split(strings.TrimSpace(out), "\n") sort.Strings(actualEnv) goodEnv := []string{ @@ -750,7 +735,7 @@ func (s *DockerSuite) TestRunEnvironmentErase(c *check.C) { func (s *DockerSuite) TestRunEnvironmentOverride(c *check.C) { // TODO Windows: Environment handling is different between Linux and - // Windows and this test relies currently on lxc and unix functionality. + // Windows and this test relies currently on unix functionality. testRequires(c, DaemonIsLinux) // Test to make sure that when we use -e on env vars that are @@ -764,13 +749,7 @@ func (s *DockerSuite) TestRunEnvironmentOverride(c *check.C) { c.Fatal(err, out) } - actualEnvLxc := strings.Split(strings.TrimSpace(out), "\n") - actualEnv := []string{} - for i := range actualEnvLxc { - if actualEnvLxc[i] != "container=lxc" { - actualEnv = append(actualEnv, actualEnvLxc[i]) - } - } + actualEnv := strings.Split(strings.TrimSpace(out), "\n") sort.Strings(actualEnv) goodEnv := []string{ diff --git a/integration-cli/docker_cli_run_unix_test.go b/integration-cli/docker_cli_run_unix_test.go index ffb424f9f6..5747e471e4 100644 --- a/integration-cli/docker_cli_run_unix_test.go +++ b/integration-cli/docker_cli_run_unix_test.go @@ -17,7 +17,6 @@ import ( "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/sysinfo" - "github.com/docker/docker/pkg/units" "github.com/go-check/check" "github.com/kr/pty" ) @@ -437,22 +436,3 @@ func (s *DockerSuite) TestRunInvalidCPUShares(c *check.C) { expected = "The maximum allowed cpu-shares is" c.Assert(out, checker.Contains, expected) } - -func (s *DockerSuite) TestRunWithCorrectMemorySwapOnLXC(c *check.C) { - testRequires(c, memoryLimitSupport) - testRequires(c, swapMemorySupport) - testRequires(c, SameHostDaemon) - - out, _ := dockerCmd(c, "run", "-d", "-m", "32m", "--memory-swap", "64m", "busybox", "top") - if _, err := os.Stat("/sys/fs/cgroup/memory/lxc"); err != nil { - c.Skip("Excecution driver must be LXC for this test") - } - id := strings.TrimSpace(out) - memorySwap, err := ioutil.ReadFile(fmt.Sprintf("/sys/fs/cgroup/memory/lxc/%s/memory.memsw.limit_in_bytes", id)) - c.Assert(err, check.IsNil) - cgSwap, err := strconv.ParseInt(strings.TrimSpace(string(memorySwap)), 10, 64) - c.Assert(err, check.IsNil) - swap, err := units.RAMInBytes("64m") - c.Assert(err, check.IsNil) - c.Assert(cgSwap, check.Equals, swap) -} diff --git a/man/docker-create.1.md b/man/docker-create.1.md index 3620004005..5317f18073 100644 --- a/man/docker-create.1.md +++ b/man/docker-create.1.md @@ -37,7 +37,6 @@ docker-create - Create a new container [**--link**[=*[]*]] [**--log-driver**[=*[]*]] [**--log-opt**[=*[]*]] -[**--lxc-conf**[=*[]*]] [**-m**|**--memory**[=*MEMORY*]] [**--mac-address**[=*MAC-ADDRESS*]] [**--memory-reservation**[=*MEMORY-RESERVATION*]] @@ -182,9 +181,6 @@ millions of trillions. **--log-opt**=[] Logging driver specific options. -**--lxc-conf**=[] - (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" - **-m**, **--memory**="" Memory limit (format: <number>[<unit>], where unit = b, k, m or g) diff --git a/man/docker-inspect.1.md b/man/docker-inspect.1.md index 34dd04a93a..b738f43952 100644 --- a/man/docker-inspect.1.md +++ b/man/docker-inspect.1.md @@ -111,7 +111,6 @@ To get information on a container use its ID or instance name: "HostConfig": { "Binds": null, "ContainerIDFile": "", - "LxcConf": [], "Memory": 0, "MemorySwap": 0, "CpuShares": 0, diff --git a/man/docker-run.1.md b/man/docker-run.1.md index e556ecfbd6..472b71f2be 100644 --- a/man/docker-run.1.md +++ b/man/docker-run.1.md @@ -38,7 +38,6 @@ docker-run - Run a command in a new container [**--link**[=*[]*]] [**--log-driver**[=*[]*]] [**--log-opt**[=*[]*]] -[**--lxc-conf**[=*[]*]] [**-m**|**--memory**[=*MEMORY*]] [**--mac-address**[=*MAC-ADDRESS*]] [**--memory-reservation**[=*MEMORY-RESERVATION*]] @@ -274,9 +273,6 @@ container can access the exposed port via a private networking interface. Docker will set some environment variables in the client container to help indicate which interface and port to use. -**--lxc-conf**=[] - (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" - **--log-driver**="|*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*awslogs*|*splunk*|*none*" Logging driver for container. Default is defined by daemon `--log-driver` flag. **Warning**: the `docker logs` command works only for the `json-file` and diff --git a/project/PACKAGERS.md b/project/PACKAGERS.md index 22f24b4789..962be12c32 100644 --- a/project/PACKAGERS.md +++ b/project/PACKAGERS.md @@ -298,7 +298,6 @@ the client will even run on alternative platforms such as Mac OS X / Darwin. Some of Docker's features are activated by using optional command-line flags or by having support for them in the kernel or userspace. A few examples include: -* LXC execution driver (requires version 1.0.7 or later of lxc and the lxc-libs) * AUFS graph driver (requires AUFS patches/support enabled in the kernel, and at least the "auplink" utility from aufs-tools) * BTRFS graph driver (requires BTRFS support enabled in the kernel) diff --git a/runconfig/hostconfig.go b/runconfig/hostconfig.go index a27d37783d..b48166e598 100644 --- a/runconfig/hostconfig.go +++ b/runconfig/hostconfig.go @@ -24,7 +24,7 @@ type NetworkMode string type IsolationLevel string // IsDefault indicates the default isolation level of a container. On Linux this -// is LXC. On Windows, this is a Windows Server Container. +// is the native driver. On Windows, this is a Windows Server Container. func (i IsolationLevel) IsDefault() bool { return strings.ToLower(string(i)) == "default" || string(i) == "" } @@ -164,69 +164,12 @@ type LogConfig struct { Config map[string]string } -// LxcConfig represents the specific LXC configuration of the container. -type LxcConfig struct { - values []KeyValuePair -} - -// MarshalJSON marshals (or serializes) the LxcConfig into JSON. -func (c *LxcConfig) MarshalJSON() ([]byte, error) { - if c == nil { - return []byte{}, nil - } - return json.Marshal(c.Slice()) -} - -// UnmarshalJSON unmarshals (or deserializes) the specified byte slices from JSON to -// a LxcConfig. -func (c *LxcConfig) UnmarshalJSON(b []byte) error { - if len(b) == 0 { - return nil - } - - var kv []KeyValuePair - if err := json.Unmarshal(b, &kv); err != nil { - var h map[string]string - if err := json.Unmarshal(b, &h); err != nil { - return err - } - for k, v := range h { - kv = append(kv, KeyValuePair{k, v}) - } - } - c.values = kv - - return nil -} - -// Len returns the number of specific lxc configuration. -func (c *LxcConfig) Len() int { - if c == nil { - return 0 - } - return len(c.values) -} - -// Slice returns the specific lxc configuration into a slice of KeyValuePair. -func (c *LxcConfig) Slice() []KeyValuePair { - if c == nil { - return nil - } - return c.values -} - -// NewLxcConfig creates a LxcConfig from the specified slice of KeyValuePair. -func NewLxcConfig(values []KeyValuePair) *LxcConfig { - return &LxcConfig{values} -} - // HostConfig the non-portable Config structure of a container. // Here, "non-portable" means "dependent of the host we are running on". // Portable information *should* appear in Config. type HostConfig struct { Binds []string // List of volume bindings for this container ContainerIDFile string // File (path) where the containerId is written - LxcConf *LxcConfig // Additional lxc configuration Memory int64 // Memory limit (in bytes) MemoryReservation int64 // Memory soft limit (in bytes) MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap diff --git a/runconfig/hostconfig_test.go b/runconfig/hostconfig_test.go index 3e2eddd183..9fe3fa782d 100644 --- a/runconfig/hostconfig_test.go +++ b/runconfig/hostconfig_test.go @@ -162,53 +162,6 @@ func TestRestartPolicy(t *testing.T) { } } -func TestLxcConfigMarshalJSON(t *testing.T) { - lxcConfigs := map[*LxcConfig]string{ - nil: "", - &LxcConfig{}: "null", - &LxcConfig{ - []KeyValuePair{{"key1", "value1"}}, - }: `[{"Key":"key1","Value":"value1"}]`, - } - - for lxcconfig, expected := range lxcConfigs { - data, err := lxcconfig.MarshalJSON() - if err != nil { - t.Fatal(err) - } - if string(data) != expected { - t.Fatalf("Expected %v, got %v", expected, string(data)) - } - } -} - -func TestLxcConfigUnmarshalJSON(t *testing.T) { - keyvaluePairs := map[string][]KeyValuePair{ - "": {{"key1", "value1"}}, - "[]": {}, - `[{"Key":"key2","Value":"value2"}]`: {{"key2", "value2"}}, - } - for json, expectedParts := range keyvaluePairs { - lxcConfig := &LxcConfig{ - []KeyValuePair{{"key1", "value1"}}, - } - if err := lxcConfig.UnmarshalJSON([]byte(json)); err != nil { - t.Fatal(err) - } - - actualParts := lxcConfig.Slice() - if len(actualParts) != len(expectedParts) { - t.Fatalf("Expected %v keyvaluePairs, got %v (%v)", len(expectedParts), len(actualParts), expectedParts) - } - for index, part := range actualParts { - if part != expectedParts[index] { - t.Fatalf("Expected %v, got %v", expectedParts, actualParts) - break - } - } - } -} - func TestMergeConfigs(t *testing.T) { expectedHostname := "hostname" expectedContainerIDFile := "containerIdFile" diff --git a/runconfig/parse.go b/runconfig/parse.go index 6c1ab51741..09899e7f6a 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -62,7 +62,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe flDNSOptions = opts.NewListOpts(nil) flExtraHosts = opts.NewListOpts(opts.ValidateExtraHost) flVolumesFrom = opts.NewListOpts(nil) - flLxcOpts = opts.NewListOpts(nil) flEnvFile = opts.NewListOpts(nil) flCapAdd = opts.NewListOpts(nil) flCapDrop = opts.NewListOpts(nil) @@ -121,7 +120,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe cmd.Var(&flDNSOptions, []string{"-dns-opt"}, "Set DNS options") cmd.Var(&flExtraHosts, []string{"-add-host"}, "Add a custom host-to-IP mapping (host:ip)") cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)") - cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "Add custom lxc options") cmd.Var(&flCapAdd, []string{"-cap-add"}, "Add Linux capabilities") cmd.Var(&flCapDrop, []string{"-cap-drop"}, "Drop Linux capabilities") cmd.Var(&flGroupAdd, []string{"-group-add"}, "Add additional groups to join") @@ -223,12 +221,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe entrypoint = stringutils.NewStrSlice(*flEntrypoint) } - lc, err := parseKeyValueOpts(flLxcOpts) - if err != nil { - return nil, nil, cmd, err - } - lxcConf := NewLxcConfig(lc) - var ( domainname string hostname = *flHostname @@ -340,7 +332,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe hostConfig := &HostConfig{ Binds: binds, ContainerIDFile: *flContainerIDFile, - LxcConf: lxcConf, Memory: flMemory, MemoryReservation: MemoryReservation, MemorySwap: memorySwap, diff --git a/runconfig/parse_test.go b/runconfig/parse_test.go index e4420cf0c0..d2406b094d 100644 --- a/runconfig/parse_test.go +++ b/runconfig/parse_test.go @@ -12,7 +12,6 @@ import ( flag "github.com/docker/docker/pkg/mflag" "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/pkg/parsers" ) func parseRun(args []string) (*Config, *HostConfig, *flag.FlagSet, error) { @@ -344,35 +343,6 @@ func setupPlatformVolume(u []string, w []string) ([]string, string) { return a, s } -func TestParseLxcConfOpt(t *testing.T) { - opts := []string{"lxc.utsname=docker", "lxc.utsname = docker "} - - for _, o := range opts { - k, v, err := parsers.ParseKeyValueOpt(o) - if err != nil { - t.FailNow() - } - if k != "lxc.utsname" { - t.Fail() - } - if v != "docker" { - t.Fail() - } - } - - // With parseRun too - _, hostconfig, _, err := parseRun([]string{"lxc.utsname=docker", "lxc.utsname = docker ", "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - for _, lxcConf := range hostconfig.LxcConf.Slice() { - if lxcConf.Key != "lxc.utsname" || lxcConf.Value != "docker" { - t.Fail() - } - } - -} - // Simple parse with MacAddress validatation func TestParseWithMacAddress(t *testing.T) { invalidMacAddress := "--mac-address=invalidMacAddress" diff --git a/runconfig/parse_unix.go b/runconfig/parse_unix.go index adc92c9519..e4eb827ff9 100644 --- a/runconfig/parse_unix.go +++ b/runconfig/parse_unix.go @@ -61,8 +61,7 @@ func ValidateNetMode(c *Config, hc *HostConfig) error { } // ValidateIsolationLevel performs platform specific validation of the -// isolation level in the hostconfig structure. Linux only supports "default" -// which is LXC container isolation +// isolation level in the hostconfig structure. Linux only supports "default". func ValidateIsolationLevel(hc *HostConfig) error { // We may not be passed a host config, such as in the case of docker commit if hc == nil {