Compare commits

..

34 Commits

Author SHA1 Message Date
Michael Crosby 7c8fca2ddb Bump to version 1.6.2
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2015-05-11 15:05:16 -07:00
Michael Crosby 376188dcd3 Update libcontainer to 227771c8f611f03639f0ee
This fixes regressions for docker containers mounting into
/sys/fs/cgroup.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2015-05-11 15:05:07 -07:00
David Calavera dc610864aa Merge pull request #13072 from jfrazelle/bump_v1.6.1
Bump v1.6.1
2015-05-07 14:59:23 -07:00
Jessica Frazelle 97cd073598 Bump version to 1.6.1
Signed-off-by: Jessica Frazelle <jess@docker.com>
2015-05-07 10:07:01 -07:00
Michael Crosby d5ebb60bdd Allow libcontainer to eval symlink destination
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>

Add tests for mounting into /proc and /sys

These two locations should be prohibited from mounting volumes into
those destinations.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2015-04-30 14:08:02 -07:00
Michael Crosby 83c5131acd Update libcontainer to 1b471834b45063b61e0aedefbb1
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2015-04-30 14:07:52 -07:00
Michael Crosby b6a9dc399b Mask reads from timer_stats and latency_stats
These files in /proc should not be able to be read as well
as written to.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2015-04-30 10:25:26 -07:00
Michael Crosby 614a9690e7 Mount RO for timer_stats and latency_stats in proc
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2015-04-22 11:15:26 -07:00
Michael Crosby 545b440a80 Mount /proc/fs as readonly
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2015-04-22 11:15:17 -07:00
Michael Crosby 3162024e28 Prevent write access to /proc/asound
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>

Conflicts:
	integration-cli/docker_cli_run_test.go
2015-04-22 11:14:46 -07:00
Jessie Frazelle 769acfec29 Merge pull request #11635 from jfrazelle/bump_v1.6.0
Bump v1.6.0
2015-04-16 12:31:02 -07:00
Jessica Frazelle 47496519da Bump version to v1.6.0
Docker-DCO-1.1-Signed-off-by: Jessie Frazelle <princess@docker.com> (github: jfrazelle)
2015-04-16 11:38:05 -07:00
Mary Anthony fdd21bf032 for 1.6
Signed-off-by: Mary Anthony <mary@docker.com>
(cherry picked from commit f44aa3b1fb)
2015-04-16 11:37:59 -07:00
Mary Anthony d928dad8c8 In with the old menu layout
Signed-off-by: Mary Anthony <mary@docker.com>
(cherry picked from commit fe8fb24b53)
2015-04-15 21:34:50 -07:00
Mary Anthony 82366ce059 Adding environment variables for sub projects
Fixes issue #12186
Fixing variables per Jess

Signed-off-by: Mary Anthony <mary@docker.com>
(cherry picked from commit ef8b917fac)
2015-04-15 21:34:49 -07:00
Mary Anthony 6410c3c066 Updating with man pages for distribution
Went through the man pages to update for the
v2 instance. Checked against the commands.

Signed-off-by: Mary Anthony <mary@docker.com>
(cherry picked from commit b6d55ebcbc)
2015-04-15 21:34:49 -07:00
Michael Crosby 9231dc9cc0 Ensure state is destroyed on daemont restart
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
(cherry picked from commit a5f7c4aa31)
2015-04-15 21:34:49 -07:00
Deng Guangxing 6a3f37386b Inspect show right LogPath in json-file driver
Signed-off-by: Deng Guangxing <dengguangxing@huawei.com>
(cherry picked from commit acf025ad1b)
2015-04-15 17:37:43 -07:00
Darren Shepherd d9a0c05208 Change syslog format and facility
This patch changes two things

1. Set facility to LOG_DAEMON
2. Remove ": " from tag so that the tag + pid become a single column in
   the log

Signed-off-by: Darren Shepherd <darren@rancher.com>
(cherry picked from commit 05641ccffc)
2015-04-15 14:49:24 -07:00
Jessica Frazelle 24cb9df189 try to modprobe bridge
Signed-off-by: Jessica Frazelle <jess@docker.com>
(cherry picked from commit b3867b8899)
2015-04-15 09:10:56 -07:00
Lewis Marshall c51cd3298c Prevent Upstart post-start stanza from hanging
Once the job has failed and is respawned, the status becomes `docker
respawn/post-start` after subsequent failures (as opposed to `docker
stop/post-start`), so the post-start script needs to take this into
account.

I could not find specific documentation on the job transitioning to the
`respawn/post-start` state, but this was observed on Ubuntu 14.04.2.

Signed-off-by: Lewis Marshall <lewis@lmars.net>
(cherry picked from commit 302e3834a0)
2015-04-14 16:23:59 -07:00
Alexander Morozov 10affa8018 Get process list after PID 1 dead
Fix #11087

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
(cherry picked from commit ac8bd12b39)
2015-04-13 12:28:22 -07:00
Deng Guangxing ce27fa2716 move syslog-tag to syslog.New function
Signed-off-by: Deng Guangxing <dengguangxing@huawei.com>
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
(cherry picked from commit 4f91a333d5)
2015-04-13 12:17:26 -07:00
Brendan Dixon 8d83409e85 Turned off Ctrl+C processing by Windows shell
Signed-off-by: Brendan Dixon <brendand@microsoft.com>
(cherry picked from commit c337bfd2e0)
2015-04-10 16:41:59 -07:00
Nathan LeClaire 3a73b6a2bf Allow SEO crawling from docs site
Signed-off-by: Nathan LeClaire <nathan.leclaire@gmail.com>

Docker-DCO-1.1-Signed-off-by: Nathan LeClaire <nathan.leclaire@gmail.com> (github: nathanleclaire)

(cherry picked from commit de03f4797b)
2015-04-10 15:59:35 -07:00
Tianon Gravi f99269882f Commonalize more bits of install.sh (especially standardizing around "cat <<-EOF")
Signed-off-by: Andrew "Tianon" Page <admwiggin@gmail.com>
(cherry picked from commit 6842bba163)
2015-04-10 11:20:15 -07:00
Eric Windisch 568a9703ac Wrap installer in a function
This will assure that the install script will not
begin executing until after it has been downloaded should
it be utilized in a 'curl | bash' workflow.

Signed-off-by: Eric Windisch <eric@windisch.us>
(cherry picked from commit fa961ce046)
2015-04-10 11:20:15 -07:00
Aaron Welch faaeb5162d add centos to supported distros
Signed-off-by: Aaron Welch <welch@packet.net>
(cherry picked from commit a6b8f2e3fe)
2015-04-10 11:20:15 -07:00
Brendan Dixon b5613baac2 Corrected int16 overflow and buffer sizes
Signed-off-by: Brendan Dixon <brendand@microsoft.com>
(cherry picked from commit a264e1e83d)
2015-04-10 11:20:15 -07:00
Alexander Morozov c956efcd52 Update libcontainer to bd8ec36106086f72b66e1be85a81202b93503e44
Fix #12130

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
(cherry picked from commit 2f853b9493)
2015-04-07 16:22:37 -07:00
Alexander Morozov 5455864187 Test case for network mode chain container -> container -> host
Issue #12130

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
(cherry picked from commit ce69dafe4d)
2015-04-07 16:22:37 -07:00
Ahmet Alp Balkan ceb72fab34 Swap width/height in GetWinsize and monitorTtySize
Signed-off-by: Ahmet Alp Balkan <ahmetalpbalkan@gmail.com>
(cherry picked from commit 6e44246fed)
2015-04-06 16:55:38 -07:00
Brendan Dixon c6ea062a26 Windows console fixes
Corrected integer size passed to Windows
Corrected DisableEcho / SetRawTerminal to not modify state
Cleaned up and made routines more idiomatic
Corrected raw mode state bits
Removed duplicate IsTerminal
Corrected off-by-one error
Minor idiomatic change

Signed-off-by: Brendan Dixon <brendand@microsoft.com>
(cherry picked from commit 1a36a113d4)
2015-04-06 11:48:33 -07:00
Ahmet Alp Balkan 0e045ab50c docs: Add new windows installation tutorials
Updated Windows installation documentation with newest
screencasts and Chocolatey instructions to install windows
client CLI.

Signed-off-by: Ahmet Alp Balkan <ahmetalpbalkan@gmail.com>
(cherry picked from commit 2b320a2309)
2015-04-03 13:51:53 -07:00
49 changed files with 983 additions and 561 deletions
+18
View File
@@ -1,5 +1,22 @@
# Changelog
## 1.6.2 (2015-05-13)
#### Runtime
- Revert change prohibiting mounting into /sys
## 1.6.1 (2015-05-07)
#### Security
- Fix read/write /proc paths (CVE-2015-3630)
- Prohibit VOLUME /proc and VOLUME / (CVE-2015-3631)
- Fix opening of file-descriptor 1 (CVE-2015-3627)
- Fix symlink traversal on container respawn allowing local privilege escalation (CVE-2015-3629)
- Prohibit mount of /sys
#### Runtime
- Update Apparmor policy to not allow mounts
## 1.6.0 (2015-04-07)
#### Builder
@@ -7,6 +24,7 @@
+ build containers with resource constraints, ie `docker build --cpu-shares=100 --memory=1024m...`
+ `commit --change` to apply specified Dockerfile instructions while committing the image
+ `import --change` to apply specified Dockerfile instructions while importing the image
+ basic build cancellation
#### Client
+ Windows Support
+1 -1
View File
@@ -1 +1 @@
1.6.0-rc4
1.6.2
+3 -3
View File
@@ -281,16 +281,16 @@ func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
if runtime.GOOS == "windows" {
go func() {
prevW, prevH := cli.getTtySize()
prevH, prevW := cli.getTtySize()
for {
time.Sleep(time.Millisecond * 250)
w, h := cli.getTtySize()
h, w := cli.getTtySize()
if prevW != w || prevH != h {
cli.resizeTty(id, isExec)
}
prevW = w
prevH = h
prevW = w
}
}()
} else {
+1 -1
View File
@@ -49,7 +49,7 @@ post-start script
fi
if ! printf "%s" "$DOCKER_OPTS" | grep -qE -e '-H|--host'; then
while ! [ -e /var/run/docker.sock ]; do
initctl status $UPSTART_JOB | grep -q "stop/" && exit 1
initctl status $UPSTART_JOB | grep -qE "(stop|respawn)/" && exit 1
echo "Waiting for /var/run/docker.sock"
sleep 0.1
done
+1
View File
@@ -1379,6 +1379,7 @@ func (container *Container) startLogging() error {
if err != nil {
return err
}
container.LogPath = pth
dl, err := jsonfilelog.New(pth)
if err != nil {
+1 -12
View File
@@ -287,19 +287,8 @@ func (daemon *Daemon) register(container *Container, updateSuffixarray bool) err
if err := container.ToDisk(); err != nil {
log.Debugf("saving stopped state to disk %s", err)
}
info := daemon.execDriver.Info(container.ID)
if !info.IsRunning() {
log.Debugf("Container %s was supposed to be running but is not.", container.ID)
log.Debugf("Marking as stopped")
container.SetStopped(&execdriver.ExitStatus{ExitCode: -127})
if err := container.ToDisk(); err != nil {
return err
}
}
}
return nil
}
+1 -8
View File
@@ -6,12 +6,10 @@ import (
"errors"
"fmt"
"net"
"path/filepath"
"strings"
"syscall"
"github.com/docker/docker/daemon/execdriver"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/libcontainer/apparmor"
"github.com/docker/libcontainer/configs"
"github.com/docker/libcontainer/devices"
@@ -228,10 +226,6 @@ func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) e
container.Mounts = defaultMounts
for _, m := range c.Mounts {
dest, err := symlink.FollowSymlinkInScope(filepath.Join(c.Rootfs, m.Destination), c.Rootfs)
if err != nil {
return err
}
flags := syscall.MS_BIND | syscall.MS_REC
if !m.Writable {
flags |= syscall.MS_RDONLY
@@ -239,10 +233,9 @@ func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) e
if m.Slave {
flags |= syscall.MS_SLAVE
}
container.Mounts = append(container.Mounts, &configs.Mount{
Source: m.Source,
Destination: dest,
Destination: m.Destination,
Device: "bind",
Flags: flags,
})
+34 -24
View File
@@ -190,6 +190,34 @@ func notifyOnOOM(container libcontainer.Container) <-chan struct{} {
return oom
}
func killCgroupProcs(c libcontainer.Container) {
var procs []*os.Process
if err := c.Pause(); err != nil {
log.Warn(err)
}
pids, err := c.Processes()
if err != nil {
// don't care about childs if we can't get them, this is mostly because cgroup already deleted
log.Warnf("Failed to get processes from container %s: %v", c.ID(), err)
}
for _, pid := range pids {
if p, err := os.FindProcess(pid); err == nil {
procs = append(procs, p)
if err := p.Kill(); err != nil {
log.Warn(err)
}
}
}
if err := c.Resume(); err != nil {
log.Warn(err)
}
for _, p := range procs {
if _, err := p.Wait(); err != nil {
log.Warn(err)
}
}
}
func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*os.ProcessState, error) {
return func() (*os.ProcessState, error) {
pid, err := p.Pid()
@@ -197,8 +225,6 @@ func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*o
return nil, err
}
processes, err := c.Processes()
process, err := os.FindProcess(pid)
s, err := process.Wait()
if err != nil {
@@ -208,19 +234,7 @@ func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*o
}
s = execErr.ProcessState
}
if err != nil {
return s, err
}
for _, pid := range processes {
process, err := os.FindProcess(pid)
if err != nil {
log.Errorf("Failed to kill process: %d", pid)
continue
}
process.Kill()
}
killCgroupProcs(c)
p.Wait()
return s, err
}
@@ -256,29 +270,25 @@ func (d *driver) Unpause(c *execdriver.Command) error {
func (d *driver) Terminate(c *execdriver.Command) error {
defer d.cleanContainer(c.ID)
// lets check the start time for the process
active := d.activeContainers[c.ID]
if active == nil {
return fmt.Errorf("active container for %s does not exist", c.ID)
container, err := d.factory.Load(c.ID)
if err != nil {
return err
}
state, err := active.State()
defer container.Destroy()
state, err := container.State()
if err != nil {
return err
}
pid := state.InitProcessPid
currentStartTime, err := system.GetProcessStartTime(pid)
if err != nil {
return err
}
if state.InitProcessStartTime == currentStartTime {
err = syscall.Kill(pid, 9)
syscall.Wait4(pid, nil, 0, nil)
}
return err
}
func (d *driver) Info(id string) execdriver.Info {
@@ -82,9 +82,16 @@ func New() *configs.Config {
},
MaskPaths: []string{
"/proc/kcore",
"/proc/latency_stats",
"/proc/timer_stats",
},
ReadonlyPaths: []string{
"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",
"/proc/asound",
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger",
},
}
+3 -12
View File
@@ -17,29 +17,20 @@ type Syslog struct {
}
func New(tag string) (logger.Logger, error) {
log, err := syslog.New(syslog.LOG_USER, path.Base(os.Args[0]))
log, err := syslog.New(syslog.LOG_DAEMON, fmt.Sprintf("%s/%s", path.Base(os.Args[0]), tag))
if err != nil {
return nil, err
}
return &Syslog{
writer: log,
tag: tag,
}, nil
}
func (s *Syslog) Log(msg *logger.Message) error {
logMessage := fmt.Sprintf("%s: %s", s.tag, string(msg.Line))
if msg.Source == "stderr" {
if err := s.writer.Err(logMessage); err != nil {
return err
}
} else {
if err := s.writer.Info(logMessage); err != nil {
return err
}
return s.writer.Err(string(msg.Line))
}
return nil
return s.writer.Info(string(msg.Line))
}
func (s *Syslog) Close() error {
+8
View File
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"net"
"os"
"os/exec"
"strings"
"sync"
@@ -106,6 +107,13 @@ func InitDriver(job *engine.Job) engine.Status {
fixedCIDR = job.Getenv("FixedCIDR")
fixedCIDRv6 = job.Getenv("FixedCIDRv6")
)
// try to modprobe bridge first
// see gh#12177
if out, err := exec.Command("modprobe", "-va", "bridge", "nf_nat").Output(); err != nil {
log.Warnf("Running modprobe bridge nf_nat failed with message: %s, error: %v", out, err)
}
initPortMapper()
if defaultIP := job.Getenv("DefaultBindingIP"); defaultIP != "" {
+61 -20
View File
@@ -4,11 +4,20 @@
FROM docs/base:latest
MAINTAINER Sven Dowideit <SvenDowideit@docker.com> (@SvenDowideit)
# This section ensures we pull the correct version of each
# sub project
ENV COMPOSE_BRANCH 1.2.0
ENV SWARM_BRANCH v0.2.0
ENV MACHINE_BRANCH master
ENV DISTRIB_BRANCH master
# TODO: need the full repo source to get the git version info
COPY . /src
# Reset the /docs dir so we can replace the theme meta with the new repo's git info
RUN git reset --hard
# RUN git reset --hard
# Then copy the desired docs into the /docs/sources/ dir
COPY ./sources/ /docs/sources
@@ -23,45 +32,77 @@ COPY ./mkdocs.yml mkdocs.yml
COPY ./s3_website.json s3_website.json
COPY ./release.sh release.sh
# Docker Distribution
#
#ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/mkdocs.yml /docs/mkdocs-distribution.yml
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/images/notifications.png /docs/sources/registry/images/notifications.png
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/images/registry.png /docs/sources/registry/images/registry.png
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/overview.md /docs/sources/registry/overview.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/registry/overview.md
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/deploying.md /docs/sources/registry/deploying.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/registry/deploying.md
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/configuration.md /docs/sources/registry/configuration.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/registry/configuration.md
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/storagedrivers.md /docs/sources/registry/storagedrivers.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/registry/storagedrivers.md
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/notifications.md /docs/sources/registry/notifications.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/registry/notifications.md
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/spec/api.md /docs/sources/registry/spec/api.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/registry/spec/api.md
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/spec/json.md /docs/sources/registry/spec/json.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/registry/spec/json.md
ADD https://raw.githubusercontent.com/docker/distribution/${DISTRIB_BRANCH}/docs/spec/auth/token.md /docs/sources/registry/spec/auth/token.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/registry/spec/auth/token.md
# Docker Swarm
#ADD https://raw.githubusercontent.com/docker/swarm/master/docs/mkdocs.yml /docs/mkdocs-swarm.yml
ADD https://raw.githubusercontent.com/docker/swarm/master/docs/index.md /docs/sources/swarm/index.md
#ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/docs/mkdocs.yml /docs/mkdocs-swarm.yml
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/docs/index.md /docs/sources/swarm/index.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/swarm/index.md
ADD https://raw.githubusercontent.com/docker/swarm/master/discovery/README.md /docs/sources/swarm/discovery.md
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/discovery/README.md /docs/sources/swarm/discovery.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/swarm/discovery.md
ADD https://raw.githubusercontent.com/docker/swarm/master/api/README.md /docs/sources/swarm/API.md
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/api/README.md /docs/sources/swarm/API.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/swarm/API.md
ADD https://raw.githubusercontent.com/docker/swarm/master/scheduler/filter/README.md /docs/sources/swarm/scheduler/filter.md
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/scheduler/filter/README.md /docs/sources/swarm/scheduler/filter.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/swarm/scheduler/filter.md
ADD https://raw.githubusercontent.com/docker/swarm/master/scheduler/strategy/README.md /docs/sources/swarm/scheduler/strategy.md
ADD https://raw.githubusercontent.com/docker/swarm/${SWARM_BRANCH}/scheduler/strategy/README.md /docs/sources/swarm/scheduler/strategy.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/swarm/scheduler/strategy.md
# Docker Machine
#ADD https://raw.githubusercontent.com/docker/machine/master/docs/mkdocs.yml /docs/mkdocs-machine.yml
ADD https://raw.githubusercontent.com/docker/machine/master/docs/index.md /docs/sources/machine/index.md
#ADD https://raw.githubusercontent.com/docker/machine/${MACHINE_BRANCH}/docs/mkdocs.yml /docs/mkdocs-machine.yml
ADD https://raw.githubusercontent.com/docker/machine/${MACHINE_BRANCH}/docs/index.md /docs/sources/machine/index.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/machine/index.md
# Docker Compose
#ADD https://raw.githubusercontent.com/docker/compose/master/docs/mkdocs.yml /docs/mkdocs-compose.yml
ADD https://raw.githubusercontent.com/docker/compose/master/docs/index.md /docs/sources/compose/index.md
#ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/mkdocs.yml /docs/mkdocs-compose.yml
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/index.md /docs/sources/compose/index.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/index.md
ADD https://raw.githubusercontent.com/docker/compose/master/docs/install.md /docs/sources/compose/install.md
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/install.md /docs/sources/compose/install.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/install.md
ADD https://raw.githubusercontent.com/docker/compose/master/docs/cli.md /docs/sources/compose/cli.md
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/cli.md /docs/sources/compose/cli.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/cli.md
ADD https://raw.githubusercontent.com/docker/compose/master/docs/yml.md /docs/sources/compose/yml.md
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/yml.md /docs/sources/compose/yml.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/yml.md
ADD https://raw.githubusercontent.com/docker/compose/master/docs/env.md /docs/sources/compose/env.md
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/env.md /docs/sources/compose/env.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/env.md
ADD https://raw.githubusercontent.com/docker/compose/master/docs/completion.md /docs/sources/compose/completion.md
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/completion.md /docs/sources/compose/completion.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/completion.md
ADD https://raw.githubusercontent.com/docker/compose/master/docs/django.md /docs/sources/compose/django.md
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/django.md /docs/sources/compose/django.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/django.md
ADD https://raw.githubusercontent.com/docker/compose/master/docs/rails.md /docs/sources/compose/rails.md
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/rails.md /docs/sources/compose/rails.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/rails.md
ADD https://raw.githubusercontent.com/docker/compose/master/docs/wordpress.md /docs/sources/compose/wordpress.md
ADD https://raw.githubusercontent.com/docker/compose/${COMPOSE_BRANCH}/docs/wordpress.md /docs/sources/compose/wordpress.md
RUN sed -i.old '1s;^;no_version_dropdown: true;' /docs/sources/compose/wordpress.md
# Then build everything together, ready for mkdocs
RUN /docs/build.sh
RUN /docs/build.sh
+11 -5
View File
@@ -2,7 +2,7 @@
% Docker Community
% JUNE 2014
# NAME
docker-login - Register or log in to a Docker registry server, if no server is specified "https://index.docker.io/v1/" is the default.
docker-login - Register or log in to a Docker registry.
# SYNOPSIS
**docker login**
@@ -13,9 +13,14 @@ docker-login - Register or log in to a Docker registry server, if no server is s
[SERVER]
# DESCRIPTION
Register or Login to a docker registry server, if no server is
specified "https://index.docker.io/v1/" is the default. If you want to
login to a private registry you can specify this by adding the server name.
Register or log in to a Docker Registry Service located on the specified
`SERVER`. You can specify a URL or a `hostname` for the `SERVER` value. If you
do not specify a `SERVER`, the command uses Docker's public registry located at
`https://registry-1.docker.io/` by default. To get a username/password for Docker's public registry, create an account on Docker Hub.
You can log into any public or private repository for which you have
credentials. When you log in, the command stores encoded credentials in
`$HOME/.dockercfg` on Linux or `%USERPROFILE%/.dockercfg` on Windows.
# OPTIONS
**-e**, **--email**=""
@@ -32,7 +37,7 @@ login to a private registry you can specify this by adding the server name.
# EXAMPLES
## Login to a local registry
## Login to a registry on your localhost
# docker login localhost:8080
@@ -43,3 +48,4 @@ login to a private registry you can specify this by adding the server name.
April 2014, Originally compiled by William Henry (whenry at redhat dot com)
based on docker.com source material and internal work.
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
April 2015, updated by Mary Anthony for v2 <mary@docker.com>
+7 -5
View File
@@ -2,23 +2,24 @@
% Docker Community
% JUNE 2014
# NAME
docker-logout - Log out from a Docker registry, if no server is specified "https://index.docker.io/v1/" is the default.
docker-logout - Log out from a Docker Registry Service.
# SYNOPSIS
**docker logout**
[SERVER]
# DESCRIPTION
Log the user out from a Docker registry, if no server is
specified "https://index.docker.io/v1/" is the default. If you want to
log out from a private registry you can specify this by adding the server name.
Log out of a Docker Registry Service located on the specified `SERVER`. You can
specify a URL or a `hostname` for the `SERVER` value. If you do not specify a
`SERVER`, the command attempts to log you out of Docker's public registry
located at `https://registry-1.docker.io/` by default.
# OPTIONS
There are no available options.
# EXAMPLES
## Log out from a local registry
## Log out from a registry on your localhost
# docker logout localhost:8080
@@ -28,3 +29,4 @@ There are no available options.
# HISTORY
June 2014, Originally compiled by Daniel, Dao Quang Minh (daniel at nitrous dot io)
July 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
April 2015, updated by Mary Anthony for v2 <mary@docker.com>
+8 -4
View File
@@ -2,7 +2,7 @@
% Docker Community
% JUNE 2014
# NAME
docker-pull - Pull an image or a repository from the registry
docker-pull - Pull an image or a repository from a registry
# SYNOPSIS
**docker pull**
@@ -12,10 +12,12 @@ NAME[:TAG]
# DESCRIPTION
This command pulls down an image or a repository from the registry. If
This command pulls down an image or a repository from a registry. If
there is more than one image for a repository (e.g., fedora) then all
images for that repository name are pulled down including any tags.
It is also possible to specify a non-default registry to pull from.
If you do not specify a `REGISTRY_HOST`, the command uses Docker's public
registry located at `registry-1.docker.io` by default.
# OPTIONS
**-a**, **--all-tags**=*true*|*false*
@@ -45,7 +47,7 @@ It is also possible to specify a non-default registry to pull from.
fedora heisenbug 105182bb5e8b 5 days ago 372.7 MB
fedora latest 105182bb5e8b 5 days ago 372.7 MB
# Pull an image, manually specifying path to the registry and tag
# Pull an image, manually specifying path to Docker's public registry and tag
# Note that if the image is previously downloaded then the status would be
# 'Status: Image is up to date for registry.hub.docker.com/fedora:20'
@@ -67,3 +69,5 @@ April 2014, Originally compiled by William Henry (whenry at redhat dot com)
based on docker.com source material and internal work.
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
August 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
April 2015, updated by John Willis <john.willis@docker.com>
April 2015, updated by Mary Anthony for v2 <mary@docker.com>
+12 -12
View File
@@ -2,18 +2,18 @@
% Docker Community
% JUNE 2014
# NAME
docker-push - Push an image or a repository to the registry
docker-push - Push an image or a repository to a registry
# SYNOPSIS
**docker push**
[**--help**]
NAME[:TAG]
NAME[:TAG] | [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]
# DESCRIPTION
Push an image or a repository to a registry. The default registry is the Docker
Hub located at [hub.docker.com](https://hub.docker.com/). However the
image can be pushed to another, perhaps private, registry as demonstrated in
the example below.
This command pushes an image or a repository to a registry. If you do not
specify a `REGISTRY_HOST`, the command uses Docker's public registry located at
`registry-1.docker.io` by default.
# OPTIONS
**--help**
@@ -28,12 +28,10 @@ and then committing it to a new image name:
# docker commit c16378f943fe rhel-httpd
Now push the image to the registry using the image ID. In this example
the registry is on host named registry-host and listening on port 5000.
Default Docker commands will push to the default `hub.docker.com`
registry. Instead, push to the local registry, which is on a host called
registry-host*. To do this, tag the image with the host name or IP
address, and the port of the registry:
Now, push the image to the registry using the image ID. In this example the
registry is on host named `registry-host` and listening on port `5000`. To do
this, tag the image with the host name or IP address, and the port of the
registry:
# docker tag rhel-httpd registry-host:5000/myadmin/rhel-httpd
# docker push registry-host:5000/myadmin/rhel-httpd
@@ -49,3 +47,5 @@ listed.
April 2014, Originally compiled by William Henry (whenry at redhat dot com)
based on docker.com source material and internal work.
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
April 2015, updated by Mary Anthony for v2 <mary@docker.com>
+4 -4
View File
@@ -13,10 +13,9 @@ IMAGE [IMAGE...]
# DESCRIPTION
This will remove one or more images from the host node. This does not
remove images from a registry. You cannot remove an image of a running
container unless you use the **-f** option. To see all images on a host
use the **docker images** command.
Removes one or more images from the host node. This does not remove images from
a registry. You cannot remove an image of a running container unless you use the
**-f** option. To see all images on a host use the **docker images** command.
# OPTIONS
**-f**, **--force**=*true*|*false*
@@ -40,3 +39,4 @@ Here is an example of removing and image:
April 2014, Originally compiled by William Henry (whenry at redhat dot com)
based on docker.com source material and internal work.
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
April 2015, updated by Mary Anthony for v2 <mary@docker.com>
+9 -8
View File
@@ -14,10 +14,9 @@ TERM
# DESCRIPTION
Search an index for an image with that matches the term TERM. The table
of images returned displays the name, description (truncated by default),
number of stars awarded, whether the image is official, and whether it
is automated.
Search Docker Hub for an image with that matches the specified `TERM`. The table
of images returned displays the name, description (truncated by default), number
of stars awarded, whether the image is official, and whether it is automated.
*Note* - Search queries will only return up to 25 results
@@ -36,9 +35,9 @@ is automated.
# EXAMPLES
## Search the registry for ranked images
## Search Docker Hub for ranked images
Search the registry for the term 'fedora' and only display those images
Search a registry for the term 'fedora' and only display those images
ranked 3 or higher:
$ sudo docker search -s 3 fedora
@@ -48,9 +47,9 @@ ranked 3 or higher:
mattdm/fedora-small A small Fedora image on which to build. Co... 8
goldmann/wildfly A WildFly application server running on a ... 3 [OK]
## Search the registry for automated images
## Search Docker Hub for automated images
Search the registry for the term 'fedora' and only display automated images
Search Docker Hub for the term 'fedora' and only display automated images
ranked 1 or higher:
$ sudo docker search -s 1 -t fedora
@@ -62,3 +61,5 @@ ranked 1 or higher:
April 2014, Originally compiled by William Henry (whenry at redhat dot com)
based on docker.com source material and internal work.
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
April 2015, updated by Mary Anthony for v2 <mary@docker.com>
+8 -3
View File
@@ -8,11 +8,14 @@ docker-tag - Tag an image into a repository
**docker tag**
[**-f**|**--force**[=*false*]]
[**--help**]
IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
IMAGE[:TAG] [REGISTRY_HOST/][USERNAME/]NAME[:TAG]
# DESCRIPTION
This will give a new alias to an image in the repository. This refers to the
entire image name including the optional TAG after the ':'.
Assigns a new alias to an image in a registry. An alias refers to the
entire image name including the optional `TAG` after the ':'.
If you do not specify a `REGISTRY_HOST`, the command uses Docker's public
registry located at `registry-1.docker.io` by default.
# "OPTIONS"
**-f**, **--force**=*true*|*false*
@@ -58,3 +61,5 @@ April 2014, Originally compiled by William Henry (whenry at redhat dot com)
based on docker.com source material and internal work.
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
July 2014, updated by Sven Dowideit <SvenDowideit@home.org.au>
April 2015, updated by Mary Anthony for v2 <mary@docker.com>
+4 -4
View File
@@ -172,10 +172,10 @@ inside it)
Load an image from a tar archive
**docker-login(1)**
Register or Login to a Docker registry server
Register or login to a Docker Registry Service
**docker-logout(1)**
Log the user out of a Docker registry server
Log the user out of a Docker Registry Service
**docker-logs(1)**
Fetch the logs of a container
@@ -190,10 +190,10 @@ inside it)
List containers
**docker-pull(1)**
Pull an image or a repository from a Docker registry server
Pull an image or a repository from a Docker Registry Service
**docker-push(1)**
Push an image or a repository to a Docker registry server
Push an image or a repository to a Docker Registry Service
**docker-restart(1)**
Restart a running container
+12 -3
View File
@@ -132,10 +132,19 @@ pages:
- ['swarm/scheduler/filter.md', 'Reference', 'Swarm filters']
- ['swarm/API.md', 'Reference', 'Swarm API']
- ['reference/api/index.md', '**HIDDEN**']
- ['registry/overview.md', 'Reference', 'Docker Registry 2.0']
- ['registry/deploying.md', 'Reference', '&nbsp;&nbsp;&nbsp;&nbsp;&blacksquare;&nbsp; Deploy a registry' ]
- ['registry/configuration.md', 'Reference', '&nbsp;&nbsp;&nbsp;&nbsp;&blacksquare;&nbsp; Configure a registry' ]
- ['registry/storagedrivers.md', 'Reference', '&nbsp;&nbsp;&nbsp;&nbsp;&blacksquare;&nbsp; Storage driver model' ]
- ['registry/notifications.md', 'Reference', '&nbsp;&nbsp;&nbsp;&nbsp;&blacksquare;&nbsp; Work with notifications' ]
- ['registry/spec/api.md', 'Reference', '&nbsp;&nbsp;&nbsp;&nbsp;&blacksquare;&nbsp; Registry Service API v2' ]
- ['registry/spec/json.md', 'Reference', '&nbsp;&nbsp;&nbsp;&nbsp;&blacksquare;&nbsp; JSON format' ]
- ['registry/spec/auth/token.md', 'Reference', '&nbsp;&nbsp;&nbsp;&nbsp;&blacksquare;&nbsp; Authenticate via central service' ]
- ['reference/api/hub_registry_spec.md', 'Reference', 'Docker Hub and Registry 1.0']
- ['reference/api/registry_api.md', 'Reference', '&nbsp;&nbsp;&nbsp;&nbsp;&blacksquare;&nbsp;Docker Registry API v1']
- ['reference/api/registry_api_client_libraries.md', 'Reference', '&nbsp;&nbsp;&nbsp;&nbsp;&blacksquare;&nbsp;Docker Registry 1.0 API Client Libraries']
#- ['reference/image-spec-v1.md', 'Reference', 'Docker Image Specification v1.0.0']
- ['reference/api/docker-io_api.md', 'Reference', 'Docker Hub API']
- ['reference/api/registry_api.md', 'Reference', 'Docker Registry API']
- ['reference/api/registry_api_client_libraries.md', 'Reference', 'Docker Registry API Client Libraries']
- ['reference/api/hub_registry_spec.md', 'Reference', 'Docker Hub and Registry Spec']
#- ['reference/image-spec-v1.md', 'Reference', 'Docker Image Specification v1.0.0']
- ['reference/api/docker_remote_api.md', 'Reference', 'Docker Remote API']
- ['reference/api/docker_remote_api_v1.18.md', 'Reference', 'Docker Remote API v1.18']
+11 -4
View File
@@ -22,10 +22,17 @@ EOF
}
create_robots_txt() {
cat > ./sources/robots.txt <<'EOF'
User-agent: *
Disallow: /
EOF
if [ "$AWS_S3_BUCKET" == "docs.docker.com" ]; then
cat > ./sources/robots.txt <<-'EOF'
User-agent: *
Allow: /
EOF
else
cat > ./sources/robots.txt <<-'EOF'
User-agent: *
Disallow: /
EOF
fi
}
setup_s3() {
+2 -1
View File
@@ -39,7 +39,8 @@
{ "Condition": { "KeyPrefixEquals": "installation/openSUSE/" }, "Redirect": { "HostName": "$BUCKET", "ReplaceKeyPrefixWith": "installation/SUSE/" } },
{ "Condition": { "KeyPrefixEquals": "contributing/contributing/" }, "Redirect": { "HostName": "$BUCKET", "ReplaceKeyPrefixWith": "project/who-written-for/" } },
{ "Condition": { "KeyPrefixEquals": "contributing/devenvironment/" }, "Redirect": { "HostName": "$BUCKET", "ReplaceKeyPrefixWith": "project/set-up-prereqs/" } },
{ "Condition": { "KeyPrefixEquals": "contributing/docs_style-guide/" }, "Redirect": { "HostName": "$BUCKET", "ReplaceKeyPrefixWith": "project/doc-style/" } }
{ "Condition": { "KeyPrefixEquals": "contributing/docs_style-guide/" }, "Redirect": { "HostName": "$BUCKET", "ReplaceKeyPrefixWith": "project/doc-style/" } },
{ "Condition": { "KeyPrefixEquals": "registry/" }, "Redirect": { "HostName": "$BUCKET", "ReplaceKeyPrefixWith": "registry/overview/" } }
]
}
+8 -1
View File
@@ -22,7 +22,7 @@ is developed, you can launch only Linux containers from your Windows machine.
## Demonstration
<iframe width="640" height="480" src="//www.youtube.com/embed/oSHN8_uiZd4?rel=0" frameborder="0" allowfullscreen></iframe>
<iframe width="640" height="480" src="//www.youtube.com/embed/TjMU3bDX4vo?rel=0" frameborder="0" allowfullscreen></iframe>
## Installation
@@ -147,3 +147,10 @@ You can do this with
`%USERPROFILE%\.ssh\id_boot2docker`
- then click: "Save Private Key".
- Then use the saved file to login with PuTTY using `docker@127.0.0.1:2022`.
## References
If you have Docker hosts running and if you don't wish to do a
Boot2Docker installation, you can install the docker.exe using
unofficial Windows package manager Chocolately. For information
on how to do this, see [Docker package on Chocolatey](http://chocolatey.org/packages/docker).
@@ -359,7 +359,10 @@ Return low-level information on the container `id`
"MaximumRetryCount": 2,
"Name": "on-failure"
},
"LogConfig": { "Type": "json-file", Config: {} },
"LogConfig": {
"Config": null,
"Type": "json-file"
},
"SecurityOpt": null,
"VolumesFrom": null,
"Ulimits": [{}]
@@ -2,7 +2,7 @@ page_title: Registry Documentation
page_description: Documentation for docker Registry and Registry API
page_keywords: docker, registry, api, hub
# The Docker Hub and the Registry spec
# The Docker Hub and the Registry 1.0 spec
## The three roles
@@ -28,9 +28,9 @@ The Docker Hub is authoritative for that information.
There is only one instance of the Docker Hub, run and
managed by Docker Inc.
### Registry
### Docker Registry 1.0
The registry has the following characteristics:
The 1.0 registry has the following characteristics:
- It stores the images and the graph for a set of repositories
- It does not have user accounts data
+2 -2
View File
@@ -2,11 +2,11 @@ page_title: Registry API
page_description: API Documentation for Docker Registry
page_keywords: API, Docker, index, registry, REST, documentation
# Docker Registry API
# Docker Registry API v1
## Introduction
- This is the REST API for the Docker Registry
- This is the REST API for the Docker Registry 1.0
- It stores the images and the graph for a set of repositories
- It does not have user accounts data
- It has no notion of user accounts or authorization
@@ -2,7 +2,7 @@ page_title: Registry API Client Libraries
page_description: Various client libraries available to use with the Docker registry API
page_keywords: API, Docker, index, registry, REST, documentation, clients, C#, Erlang, Go, Groovy, Java, JavaScript, Perl, PHP, Python, Ruby, Rust, Scala
# Docker Registry API Client Libraries
# Docker Registry 1.0 API Client Libraries
These libraries have not been tested by the Docker maintainers for
compatibility. Please file issues with the library owners. If you find
+213 -196
View File
@@ -20,213 +20,230 @@ command_exists() {
command -v "$@" > /dev/null 2>&1
}
case "$(uname -m)" in
*64)
;;
*)
echo >&2 'Error: you are not using a 64bit platform.'
echo >&2 'Docker currently only supports 64bit platforms.'
exit 1
;;
esac
echo_docker_as_nonroot() {
your_user=your-user
[ "$user" != 'root' ] && your_user="$user"
# intentionally mixed spaces and tabs here -- tabs are stripped by "<<-EOF", spaces are kept in the output
cat <<-EOF
if command_exists docker || command_exists lxc-docker; then
echo >&2 'Warning: "docker" or "lxc-docker" command appears to already exist.'
echo >&2 'Please ensure that you do not already have docker installed.'
echo >&2 'You may press Ctrl+C now to abort this process and rectify this situation.'
( set -x; sleep 20 )
fi
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:
user="$(id -un 2>/dev/null || true)"
sudo usermod -aG docker $your_user
sh_c='sh -c'
if [ "$user" != 'root' ]; then
if command_exists sudo; then
sh_c='sudo -E sh -c'
elif command_exists su; then
sh_c='su -c'
else
echo >&2 'Error: this installer needs the ability to run commands as root.'
echo >&2 'We are unable to find either "sudo" or "su" available to make this happen.'
exit 1
Remember that you will have to log out and back in for this to take effect!
EOF
}
do_install() {
case "$(uname -m)" in
*64)
;;
*)
cat >&2 <<-'EOF'
Error: you are not using a 64bit platform.
Docker currently only supports 64bit platforms.
EOF
exit 1
;;
esac
if command_exists docker || command_exists lxc-docker; then
cat >&2 <<-'EOF'
Warning: "docker" or "lxc-docker" command appears to already exist.
Please ensure that you do not already have docker installed.
You may press Ctrl+C now to abort this process and rectify this situation.
EOF
( set -x; sleep 20 )
fi
fi
curl=''
if command_exists curl; then
curl='curl -sSL'
elif command_exists wget; then
curl='wget -qO-'
elif command_exists busybox && busybox --list-modules | grep -q wget; then
curl='busybox wget -qO-'
fi
user="$(id -un 2>/dev/null || true)"
# perform some very rudimentary platform detection
lsb_dist=''
if command_exists lsb_release; then
lsb_dist="$(lsb_release -si)"
fi
if [ -z "$lsb_dist" ] && [ -r /etc/lsb-release ]; then
lsb_dist="$(. /etc/lsb-release && echo "$DISTRIB_ID")"
fi
if [ -z "$lsb_dist" ] && [ -r /etc/debian_version ]; then
lsb_dist='debian'
fi
if [ -z "$lsb_dist" ] && [ -r /etc/fedora-release ]; then
lsb_dist='fedora'
fi
if [ -z "$lsb_dist" ] && [ -r /etc/os-release ]; then
lsb_dist="$(. /etc/os-release && echo "$ID")"
fi
lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')"
case "$lsb_dist" in
amzn|fedora)
if [ "$lsb_dist" = 'amzn' ]; then
(
set -x
$sh_c 'sleep 3; yum -y -q install docker'
)
sh_c='sh -c'
if [ "$user" != 'root' ]; then
if command_exists sudo; then
sh_c='sudo -E sh -c'
elif command_exists su; then
sh_c='su -c'
else
(
set -x
$sh_c 'sleep 3; yum -y -q install docker-io'
)
fi
if command_exists docker && [ -e /var/run/docker.sock ]; then
(
set -x
$sh_c 'docker version'
) || true
fi
your_user=your-user
[ "$user" != 'root' ] && your_user="$user"
echo
echo 'If you would like to use Docker as a non-root user, you should now consider'
echo 'adding your user to the "docker" group with something like:'
echo
echo ' sudo usermod -aG docker' $your_user
echo
echo 'Remember that you will have to log out and back in for this to take effect!'
echo
exit 0
;;
ubuntu|debian|linuxmint)
export DEBIAN_FRONTEND=noninteractive
did_apt_get_update=
apt_get_update() {
if [ -z "$did_apt_get_update" ]; then
( set -x; $sh_c 'sleep 3; apt-get update' )
did_apt_get_update=1
fi
}
# aufs is preferred over devicemapper; try to ensure the driver is available.
if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then
if uname -r | grep -q -- '-generic' && dpkg -l 'linux-image-*-generic' | grep -q '^ii' 2>/dev/null; then
kern_extras="linux-image-extra-$(uname -r) linux-image-extra-virtual"
apt_get_update
( set -x; $sh_c 'sleep 3; apt-get install -y -q '"$kern_extras" ) || true
if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then
echo >&2 'Warning: tried to install '"$kern_extras"' (for AUFS)'
echo >&2 ' but we still have no AUFS. Docker may not work. Proceeding anyways!'
( set -x; sleep 10 )
fi
else
echo >&2 'Warning: current kernel is not supported by the linux-image-extra-virtual'
echo >&2 ' package. We have no AUFS support. Consider installing the packages'
echo >&2 ' linux-image-virtual kernel and linux-image-extra-virtual for AUFS support.'
( set -x; sleep 10 )
fi
fi
# install apparmor utils if they're missing and apparmor is enabled in the kernel
# otherwise Docker will fail to start
if [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = 'Y' ]; then
if command -v apparmor_parser &> /dev/null; then
echo 'apparmor is enabled in the kernel and apparmor utils were already installed'
else
echo 'apparmor is enabled in the kernel, but apparmor_parser missing'
apt_get_update
( set -x; $sh_c 'sleep 3; apt-get install -y -q apparmor' )
fi
fi
if [ ! -e /usr/lib/apt/methods/https ]; then
apt_get_update
( set -x; $sh_c 'sleep 3; apt-get install -y -q apt-transport-https ca-certificates' )
fi
if [ -z "$curl" ]; then
apt_get_update
( set -x; $sh_c 'sleep 3; apt-get install -y -q curl ca-certificates' )
curl='curl -sSL'
fi
(
set -x
if [ "https://get.docker.com/" = "$url" ]; then
$sh_c "apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9"
elif [ "https://test.docker.com/" = "$url" ]; then
$sh_c "apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 740B314AE3941731B942C66ADF4FD13717AAD7D6"
else
$sh_c "$curl ${url}gpg | apt-key add -"
fi
$sh_c "echo deb ${url}ubuntu docker main > /etc/apt/sources.list.d/docker.list"
$sh_c 'sleep 3; apt-get update; apt-get install -y -q lxc-docker'
)
if command_exists docker && [ -e /var/run/docker.sock ]; then
(
set -x
$sh_c 'docker version'
) || true
fi
your_user=your-user
[ "$user" != 'root' ] && your_user="$user"
echo
echo 'If you would like to use Docker as a non-root user, you should now consider'
echo 'adding your user to the "docker" group with something like:'
echo
echo ' sudo usermod -aG docker' $your_user
echo
echo 'Remember that you will have to log out and back in for this to take effect!'
echo
exit 0
;;
gentoo)
if [ "$url" = "https://test.docker.com/" ]; then
echo >&2
echo >&2 ' You appear to be trying to install the latest nightly build in Gentoo.'
echo >&2 ' The portage tree should contain the latest stable release of Docker, but'
echo >&2 ' if you want something more recent, you can always use the live ebuild'
echo >&2 ' provided in the "docker" overlay available via layman. For more'
echo >&2 ' instructions, please see the following URL:'
echo >&2 ' https://github.com/tianon/docker-overlay#using-this-overlay'
echo >&2 ' After adding the "docker" overlay, you should be able to:'
echo >&2 ' emerge -av =app-emulation/docker-9999'
echo >&2
cat >&2 <<-'EOF'
Error: this installer needs the ability to run commands as root.
We are unable to find either "sudo" or "su" available to make this happen.
EOF
exit 1
fi
fi
(
set -x
$sh_c 'sleep 3; emerge app-emulation/docker'
)
exit 0
;;
esac
curl=''
if command_exists curl; then
curl='curl -sSL'
elif command_exists wget; then
curl='wget -qO-'
elif command_exists busybox && busybox --list-modules | grep -q wget; then
curl='busybox wget -qO-'
fi
cat >&2 <<'EOF'
# perform some very rudimentary platform detection
lsb_dist=''
if command_exists lsb_release; then
lsb_dist="$(lsb_release -si)"
fi
if [ -z "$lsb_dist" ] && [ -r /etc/lsb-release ]; then
lsb_dist="$(. /etc/lsb-release && echo "$DISTRIB_ID")"
fi
if [ -z "$lsb_dist" ] && [ -r /etc/debian_version ]; then
lsb_dist='debian'
fi
if [ -z "$lsb_dist" ] && [ -r /etc/fedora-release ]; then
lsb_dist='fedora'
fi
if [ -z "$lsb_dist" ] && [ -r /etc/os-release ]; then
lsb_dist="$(. /etc/os-release && echo "$ID")"
fi
Either your platform is not easily detectable, is not supported by this
installer script (yet - PRs welcome! [hack/install.sh]), or does not yet have
a package for Docker. Please visit the following URL for more detailed
installation instructions:
lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')"
case "$lsb_dist" in
amzn|fedora|centos)
if [ "$lsb_dist" = 'amzn' ]; then
(
set -x
$sh_c 'sleep 3; yum -y -q install docker'
)
else
(
set -x
$sh_c 'sleep 3; yum -y -q install docker-io'
)
fi
if command_exists docker && [ -e /var/run/docker.sock ]; then
(
set -x
$sh_c 'docker version'
) || true
fi
echo_docker_as_nonroot
exit 0
;;
https://docs.docker.com/en/latest/installation/
ubuntu|debian|linuxmint)
export DEBIAN_FRONTEND=noninteractive
EOF
exit 1
did_apt_get_update=
apt_get_update() {
if [ -z "$did_apt_get_update" ]; then
( set -x; $sh_c 'sleep 3; apt-get update' )
did_apt_get_update=1
fi
}
# aufs is preferred over devicemapper; try to ensure the driver is available.
if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then
if uname -r | grep -q -- '-generic' && dpkg -l 'linux-image-*-generic' | grep -q '^ii' 2>/dev/null; then
kern_extras="linux-image-extra-$(uname -r) linux-image-extra-virtual"
apt_get_update
( set -x; $sh_c 'sleep 3; apt-get install -y -q '"$kern_extras" ) || true
if ! grep -q aufs /proc/filesystems && ! $sh_c 'modprobe aufs'; then
echo >&2 'Warning: tried to install '"$kern_extras"' (for AUFS)'
echo >&2 ' but we still have no AUFS. Docker may not work. Proceeding anyways!'
( set -x; sleep 10 )
fi
else
echo >&2 'Warning: current kernel is not supported by the linux-image-extra-virtual'
echo >&2 ' package. We have no AUFS support. Consider installing the packages'
echo >&2 ' linux-image-virtual kernel and linux-image-extra-virtual for AUFS support.'
( set -x; sleep 10 )
fi
fi
# install apparmor utils if they're missing and apparmor is enabled in the kernel
# otherwise Docker will fail to start
if [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = 'Y' ]; then
if command -v apparmor_parser &> /dev/null; then
echo 'apparmor is enabled in the kernel and apparmor utils were already installed'
else
echo 'apparmor is enabled in the kernel, but apparmor_parser missing'
apt_get_update
( set -x; $sh_c 'sleep 3; apt-get install -y -q apparmor' )
fi
fi
if [ ! -e /usr/lib/apt/methods/https ]; then
apt_get_update
( set -x; $sh_c 'sleep 3; apt-get install -y -q apt-transport-https ca-certificates' )
fi
if [ -z "$curl" ]; then
apt_get_update
( set -x; $sh_c 'sleep 3; apt-get install -y -q curl ca-certificates' )
curl='curl -sSL'
fi
(
set -x
if [ "https://get.docker.com/" = "$url" ]; then
$sh_c "apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9"
elif [ "https://test.docker.com/" = "$url" ]; then
$sh_c "apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 740B314AE3941731B942C66ADF4FD13717AAD7D6"
else
$sh_c "$curl ${url}gpg | apt-key add -"
fi
$sh_c "echo deb ${url}ubuntu docker main > /etc/apt/sources.list.d/docker.list"
$sh_c 'sleep 3; apt-get update; apt-get install -y -q lxc-docker'
)
if command_exists docker && [ -e /var/run/docker.sock ]; then
(
set -x
$sh_c 'docker version'
) || true
fi
echo_docker_as_nonroot
exit 0
;;
gentoo)
if [ "$url" = "https://test.docker.com/" ]; then
# intentionally mixed spaces and tabs here -- tabs are stripped by "<<-'EOF'", spaces are kept in the output
cat >&2 <<-'EOF'
You appear to be trying to install the latest nightly build in Gentoo.'
The portage tree should contain the latest stable release of Docker, but'
if you want something more recent, you can always use the live ebuild'
provided in the "docker" overlay available via layman. For more'
instructions, please see the following URL:'
https://github.com/tianon/docker-overlay#using-this-overlay'
After adding the "docker" overlay, you should be able to:'
emerge -av =app-emulation/docker-9999'
EOF
exit 1
fi
(
set -x
$sh_c 'sleep 3; emerge app-emulation/docker'
)
exit 0
;;
esac
# intentionally mixed spaces and tabs here -- tabs are stripped by "<<-'EOF'", spaces are kept in the output
cat >&2 <<-'EOF'
Either your platform is not easily detectable, is not supported by this
installer script (yet - PRs welcome! [hack/install.sh]), or does not yet have
a package for Docker. Please visit the following URL for more detailed
installation instructions:
https://docs.docker.com/en/latest/installation/
EOF
exit 1
}
# wrapped up in a function so that we have some protection against only getting
# half the file during "curl | sh"
do_install
+1 -1
View File
@@ -75,7 +75,7 @@ rm -rf src/github.com/docker/distribution
mkdir -p src/github.com/docker/distribution
mv tmp-digest src/github.com/docker/distribution/digest
clone git github.com/docker/libcontainer d00b8369852285d6a830a8d3b966608b2ed89705
clone git github.com/docker/libcontainer 227771c8f611f03639f0eeb169428761d9504ab5
# see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file)
rm -rf src/github.com/docker/libcontainer/vendor
eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli' | grep -v 'github.com/Sirupsen/logrus')"
+123
View File
@@ -3237,6 +3237,35 @@ func TestRunNetHost(t *testing.T) {
logDone("run - net host mode")
}
func TestRunNetContainerWhichHost(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
hostNet, err := os.Readlink("/proc/1/ns/net")
if err != nil {
t.Fatal(err)
}
cmd := exec.Command(dockerBinary, "run", "-d", "--net=host", "--name=test", "busybox", "top")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
}
cmd = exec.Command(dockerBinary, "run", "--net=container:test", "busybox", "readlink", "/proc/self/ns/net")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
}
out = strings.Trim(out, "\n")
if hostNet != out {
t.Fatalf("Container should have host network namespace")
}
logDone("run - net container mode, where container in host mode")
}
func TestRunAllowPortRangeThroughPublish(t *testing.T) {
defer deleteAllContainers()
@@ -3382,3 +3411,97 @@ func TestRunVolumesFromRestartAfterRemoved(t *testing.T) {
logDone("run - can restart a volumes-from container after producer is removed")
}
func TestRunPidHostWithChildIsKillable(t *testing.T) {
defer deleteAllContainers()
name := "ibuildthecloud"
if out, err := exec.Command(dockerBinary, "run", "-d", "--pid=host", "--name", name, "busybox", "sh", "-c", "sleep 30; echo hi").CombinedOutput(); err != nil {
t.Fatal(err, out)
}
time.Sleep(1 * time.Second)
errchan := make(chan error)
go func() {
if out, err := exec.Command(dockerBinary, "kill", name).CombinedOutput(); err != nil {
errchan <- fmt.Errorf("%v:\n%s", err, out)
}
close(errchan)
}()
select {
case err := <-errchan:
if err != nil {
t.Fatal(err)
}
case <-time.After(5 * time.Second):
t.Fatal("Kill container timed out")
}
logDone("run - can kill container with pid-host and some childs of pid 1")
}
func TestRunWithTooSmallMemoryLimit(t *testing.T) {
defer deleteAllContainers()
// this memory limit is 1 byte less than the min, which is 4MB
// https://github.com/docker/docker/blob/v1.5.0/daemon/create.go#L22
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-m", "4194303", "busybox"))
if err == nil || !strings.Contains(out, "Minimum memory limit allowed is 4MB") {
t.Fatalf("expected run to fail when using too low a memory limit: %q", out)
}
logDone("run - can't set too low memory limit")
}
func TestRunWriteToProcAsound(t *testing.T) {
defer deleteAllContainers()
code, err := runCommand(exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "echo 111 >> /proc/asound/version"))
if err == nil || code == 0 {
t.Fatal("standard container should not be able to write to /proc/asound")
}
logDone("run - ro write to /proc/asound")
}
func TestRunReadProcTimer(t *testing.T) {
defer deleteAllContainers()
out, code, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "busybox", "cat", "/proc/timer_stats"))
if err != nil || code != 0 {
t.Fatal(err)
}
if strings.Trim(out, "\n ") != "" {
t.Fatalf("expected to receive no output from /proc/timer_stats but received %q", out)
}
logDone("run - read /proc/timer_stats")
}
func TestRunReadProcLatency(t *testing.T) {
// some kernels don't have this configured so skip the test if this file is not found
// on the host running the tests.
if _, err := os.Stat("/proc/latency_stats"); err != nil {
t.Skip()
return
}
defer deleteAllContainers()
out, code, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "busybox", "cat", "/proc/latency_stats"))
if err != nil || code != 0 {
t.Fatal(err)
}
if strings.Trim(out, "\n ") != "" {
t.Fatalf("expected to receive no output from /proc/latency_stats but received %q", out)
}
logDone("run - read /proc/latency_stats")
}
func TestMountIntoProc(t *testing.T) {
defer deleteAllContainers()
code, err := runCommand(exec.Command(dockerBinary, "run", "-v", "/proc//sys", "busybox", "true"))
if err == nil || code == 0 {
t.Fatal("container should not be able to mount into /proc")
}
logDone("run - mount into proc")
}
func TestMountIntoSys(t *testing.T) {
defer deleteAllContainers()
_, err := runCommand(exec.Command(dockerBinary, "run", "-v", "/sys/fs/cgroup", "busybox", "true"))
if err != nil {
t.Fatal("container should be able to mount into /sys")
}
logDone("run - mount into sys")
}
+59 -58
View File
@@ -5,6 +5,7 @@ import (
"io"
"os"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/term/winconsole"
)
@@ -21,34 +22,49 @@ type Winsize struct {
y uint16
}
// GetWinsize gets the window size of the given terminal
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
switch {
case os.Getenv("ConEmuANSI") == "ON":
// The ConEmu shell emulates ANSI well by default.
return os.Stdin, os.Stdout, os.Stderr
case os.Getenv("MSYSTEM") != "":
// MSYS (mingw) does not emulate ANSI well.
return winconsole.WinConsoleStreams()
default:
return winconsole.WinConsoleStreams()
}
}
// GetFdInfo returns file descriptor and bool indicating whether the file is a terminal.
func GetFdInfo(in interface{}) (uintptr, bool) {
return winconsole.GetHandleInfo(in)
}
// GetWinsize retrieves the window size of the terminal connected to the passed file descriptor.
func GetWinsize(fd uintptr) (*Winsize, error) {
ws := &Winsize{}
var info *winconsole.CONSOLE_SCREEN_BUFFER_INFO
info, err := winconsole.GetConsoleScreenBufferInfo(fd)
if err != nil {
return nil, err
}
ws.Width = uint16(info.Window.Right - info.Window.Left + 1)
ws.Height = uint16(info.Window.Bottom - info.Window.Top + 1)
ws.x = 0 // todo azlinux -- this is the pixel size of the Window, and not currently used by any caller
ws.y = 0
return ws, nil
// TODO(azlinux): Set the pixel width / height of the console (currently unused by any caller)
return &Winsize{
Width: uint16(info.Window.Right - info.Window.Left + 1),
Height: uint16(info.Window.Bottom - info.Window.Top + 1),
x: 0,
y: 0}, nil
}
// SetWinsize sets the terminal connected to the given file descriptor to a
// given size.
// SetWinsize sets the size of the given terminal connected to the passed file descriptor.
func SetWinsize(fd uintptr, ws *Winsize) error {
// TODO(azlinux): Implement SetWinsize
logrus.Debugf("[windows] SetWinsize: WARNING -- Unsupported method invoked")
return nil
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd uintptr) bool {
_, e := winconsole.GetConsoleMode(fd)
return e == nil
return winconsole.IsConsole(fd)
}
// RestoreTerminal restores the terminal connected to the given file descriptor to a
@@ -57,7 +73,7 @@ func RestoreTerminal(fd uintptr, state *State) error {
return winconsole.SetConsoleMode(fd, state.mode)
}
// SaveState saves the state of the given console
// SaveState saves the state of the terminal connected to the given file descriptor.
func SaveState(fd uintptr) (*State, error) {
mode, e := winconsole.GetConsoleMode(fd)
if e != nil {
@@ -66,72 +82,57 @@ func SaveState(fd uintptr) (*State, error) {
return &State{mode}, nil
}
// DisableEcho disbales the echo for given file descriptor and returns previous state
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx for these flag settings
// DisableEcho disables echo for the terminal connected to the given file descriptor.
// -- See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
func DisableEcho(fd uintptr, state *State) error {
state.mode &^= (winconsole.ENABLE_ECHO_INPUT)
state.mode |= (winconsole.ENABLE_PROCESSED_INPUT | winconsole.ENABLE_LINE_INPUT)
return winconsole.SetConsoleMode(fd, state.mode)
mode := state.mode
mode &^= winconsole.ENABLE_ECHO_INPUT
mode |= winconsole.ENABLE_PROCESSED_INPUT | winconsole.ENABLE_LINE_INPUT
// TODO(azlinux): Core code registers a goroutine to catch os.Interrupt and reset the terminal state.
return winconsole.SetConsoleMode(fd, mode)
}
// SetRawTerminal puts the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func SetRawTerminal(fd uintptr) (*State, error) {
oldState, err := MakeRaw(fd)
state, err := MakeRaw(fd)
if err != nil {
return nil, err
}
// TODO (azlinux): implement handling interrupt and restore state of terminal
return oldState, err
// TODO(azlinux): Core code registers a goroutine to catch os.Interrupt and reset the terminal state.
return state, err
}
// MakeRaw puts the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(fd uintptr) (*State, error) {
var state *State
state, err := SaveState(fd)
if err != nil {
return nil, err
}
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
// All three input modes, along with processed output mode, are designed to work together.
// It is best to either enable or disable all of these modes as a group.
// When all are enabled, the application is said to be in "cooked" mode, which means that most of the processing is handled for the application.
// When all are disabled, the application is in "raw" mode, which means that input is unfiltered and any processing is left to the application.
state.mode = 0
err = winconsole.SetConsoleMode(fd, state.mode)
// See
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
// -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx
mode := state.mode
// Disable these modes
mode &^= winconsole.ENABLE_ECHO_INPUT
mode &^= winconsole.ENABLE_LINE_INPUT
mode &^= winconsole.ENABLE_MOUSE_INPUT
mode &^= winconsole.ENABLE_WINDOW_INPUT
mode &^= winconsole.ENABLE_PROCESSED_INPUT
// Enable these modes
mode |= winconsole.ENABLE_EXTENDED_FLAGS
mode |= winconsole.ENABLE_INSERT_MODE
mode |= winconsole.ENABLE_QUICK_EDIT_MODE
err = winconsole.SetConsoleMode(fd, mode)
if err != nil {
return nil, err
}
return state, nil
}
// GetFdInfo returns file descriptor and bool indicating whether the file is a terminal
func GetFdInfo(in interface{}) (uintptr, bool) {
return winconsole.GetHandleInfo(in)
}
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
var shouldEmulateANSI bool
switch {
case os.Getenv("ConEmuANSI") == "ON":
// ConEmu shell, ansi emulated by default and ConEmu does an extensively
// good emulation.
shouldEmulateANSI = false
case os.Getenv("MSYSTEM") != "":
// MSYS (mingw) cannot fully emulate well and still shows escape characters
// mostly because it's still running on cmd.exe window.
shouldEmulateANSI = true
default:
shouldEmulateANSI = true
}
if shouldEmulateANSI {
return winconsole.StdStreams()
}
return os.Stdin, os.Stdout, os.Stderr
}
+94 -87
View File
@@ -12,18 +12,22 @@ import (
"sync"
"syscall"
"unsafe"
"github.com/Sirupsen/logrus"
)
const (
// Consts for Get/SetConsoleMode function
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx
ENABLE_ECHO_INPUT = 0x0004
ENABLE_INSERT_MODE = 0x0020
ENABLE_LINE_INPUT = 0x0002
ENABLE_MOUSE_INPUT = 0x0010
// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
ENABLE_PROCESSED_INPUT = 0x0001
ENABLE_QUICK_EDIT_MODE = 0x0040
ENABLE_LINE_INPUT = 0x0002
ENABLE_ECHO_INPUT = 0x0004
ENABLE_WINDOW_INPUT = 0x0008
ENABLE_MOUSE_INPUT = 0x0010
ENABLE_INSERT_MODE = 0x0020
ENABLE_QUICK_EDIT_MODE = 0x0040
ENABLE_EXTENDED_FLAGS = 0x0080
// If parameter is a screen buffer handle, additional values
ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
@@ -97,27 +101,27 @@ const (
VK_HOME = 0x24 // HOME key
VK_LEFT = 0x25 // LEFT ARROW key
VK_UP = 0x26 // UP ARROW key
VK_RIGHT = 0x27 //RIGHT ARROW key
VK_DOWN = 0x28 //DOWN ARROW key
VK_SELECT = 0x29 //SELECT key
VK_PRINT = 0x2A //PRINT key
VK_EXECUTE = 0x2B //EXECUTE key
VK_SNAPSHOT = 0x2C //PRINT SCREEN key
VK_INSERT = 0x2D //INS key
VK_DELETE = 0x2E //DEL key
VK_HELP = 0x2F //HELP key
VK_F1 = 0x70 //F1 key
VK_F2 = 0x71 //F2 key
VK_F3 = 0x72 //F3 key
VK_F4 = 0x73 //F4 key
VK_F5 = 0x74 //F5 key
VK_F6 = 0x75 //F6 key
VK_F7 = 0x76 //F7 key
VK_F8 = 0x77 //F8 key
VK_F9 = 0x78 //F9 key
VK_F10 = 0x79 //F10 key
VK_F11 = 0x7A //F11 key
VK_F12 = 0x7B //F12 key
VK_RIGHT = 0x27 // RIGHT ARROW key
VK_DOWN = 0x28 // DOWN ARROW key
VK_SELECT = 0x29 // SELECT key
VK_PRINT = 0x2A // PRINT key
VK_EXECUTE = 0x2B // EXECUTE key
VK_SNAPSHOT = 0x2C // PRINT SCREEN key
VK_INSERT = 0x2D // INS key
VK_DELETE = 0x2E // DEL key
VK_HELP = 0x2F // HELP key
VK_F1 = 0x70 // F1 key
VK_F2 = 0x71 // F2 key
VK_F3 = 0x72 // F3 key
VK_F4 = 0x73 // F4 key
VK_F5 = 0x74 // F5 key
VK_F6 = 0x75 // F6 key
VK_F7 = 0x76 // F7 key
VK_F8 = 0x77 // F8 key
VK_F9 = 0x78 // F9 key
VK_F10 = 0x79 // F10 key
VK_F11 = 0x7A // F11 key
VK_F12 = 0x7B // F12 key
)
var kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
@@ -140,7 +144,12 @@ var (
// types for calling various windows API
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx
type (
SHORT int16
SHORT int16
BOOL int32
WORD uint16
WCHAR uint16
DWORD uint32
SMALL_RECT struct {
Left SHORT
Top SHORT
@@ -153,11 +162,6 @@ type (
Y SHORT
}
BOOL int32
WORD uint16
WCHAR uint16
DWORD uint32
CONSOLE_SCREEN_BUFFER_INFO struct {
Size COORD
CursorPosition COORD
@@ -192,6 +196,10 @@ type (
}
)
// TODO(azlinux): Basic type clean-up
// -- Convert all uses of uintptr to syscall.Handle to be consistent with Windows syscall
// -- Convert, as appropriate, types to use defined Windows types (e.g., DWORD instead of uint32)
// Implements the TerminalEmulator interface
type WindowsTerminal struct {
outMutex sync.Mutex
@@ -211,14 +219,14 @@ func getStdHandle(stdhandle int) uintptr {
return uintptr(handle)
}
func StdStreams() (stdIn io.ReadCloser, stdOut io.Writer, stdErr io.Writer) {
func WinConsoleStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
handler := &WindowsTerminal{
inputBuffer: make([]byte, MAX_INPUT_BUFFER),
inputEscapeSequence: []byte(KEY_ESC_CSI),
inputEvents: make([]INPUT_RECORD, MAX_INPUT_EVENTS),
}
if IsTerminal(os.Stdin.Fd()) {
if IsConsole(os.Stdin.Fd()) {
stdIn = &terminalReader{
wrappedReader: os.Stdin,
emulator: handler,
@@ -229,7 +237,7 @@ func StdStreams() (stdIn io.ReadCloser, stdOut io.Writer, stdErr io.Writer) {
stdIn = os.Stdin
}
if IsTerminal(os.Stdout.Fd()) {
if IsConsole(os.Stdout.Fd()) {
stdoutHandle := getStdHandle(syscall.STD_OUTPUT_HANDLE)
// Save current screen buffer info
@@ -253,7 +261,7 @@ func StdStreams() (stdIn io.ReadCloser, stdOut io.Writer, stdErr io.Writer) {
stdOut = os.Stdout
}
if IsTerminal(os.Stderr.Fd()) {
if IsConsole(os.Stderr.Fd()) {
stdErr = &terminalWriter{
wrappedWriter: os.Stderr,
emulator: handler,
@@ -267,25 +275,21 @@ func StdStreams() (stdIn io.ReadCloser, stdOut io.Writer, stdErr io.Writer) {
return stdIn, stdOut, stdErr
}
// GetHandleInfo returns file descriptor and bool indicating whether the file is a terminal
// GetHandleInfo returns file descriptor and bool indicating whether the file is a console.
func GetHandleInfo(in interface{}) (uintptr, bool) {
var inFd uintptr
var isTerminalIn bool
switch t := in.(type) {
case *terminalReader:
in = t.wrappedReader
case *terminalWriter:
in = t.wrappedWriter
}
if file, ok := in.(*os.File); ok {
inFd = file.Fd()
isTerminalIn = IsTerminal(inFd)
}
if tr, ok := in.(*terminalReader); ok {
if file, ok := tr.wrappedReader.(*os.File); ok {
inFd = file.Fd()
isTerminalIn = IsTerminal(inFd)
}
}
if tr, ok := in.(*terminalWriter); ok {
if file, ok := tr.wrappedWriter.(*os.File); ok {
inFd = file.Fd()
isTerminalIn = IsTerminal(inFd)
}
isTerminalIn = IsConsole(inFd)
}
return inFd, isTerminalIn
}
@@ -318,12 +322,12 @@ func SetConsoleMode(handle uintptr, mode uint32) error {
// SetCursorVisible sets the cursor visbility
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms686019(v=vs.85).aspx
func SetCursorVisible(handle uintptr, isVisible BOOL) (bool, error) {
var cursorInfo CONSOLE_CURSOR_INFO
if err := getError(getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(&cursorInfo)), 0)); err != nil {
var cursorInfo *CONSOLE_CURSOR_INFO = &CONSOLE_CURSOR_INFO{}
if err := getError(getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)); err != nil {
return false, err
}
cursorInfo.Visible = isVisible
if err := getError(setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(&cursorInfo)), 0)); err != nil {
if err := getError(setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)); err != nil {
return false, err
}
return true, nil
@@ -408,25 +412,25 @@ func getNumberOfChars(fromCoord COORD, toCoord COORD, screenSize COORD) uint32 {
var buffer []CHAR_INFO
func clearDisplayRect(handle uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (uint32, error) {
func clearDisplayRect(handle uintptr, attributes WORD, fromCoord COORD, toCoord COORD) (uint32, error) {
var writeRegion SMALL_RECT
writeRegion.Top = fromCoord.Y
writeRegion.Left = fromCoord.X
writeRegion.Top = fromCoord.Y
writeRegion.Right = toCoord.X
writeRegion.Bottom = toCoord.Y
// allocate and initialize buffer
width := toCoord.X - fromCoord.X + 1
height := toCoord.Y - fromCoord.Y + 1
size := width * height
size := uint32(width) * uint32(height)
if size > 0 {
for i := 0; i < int(size); i++ {
buffer[i].UnicodeChar = WCHAR(fillChar)
buffer[i].Attributes = attributes
buffer := make([]CHAR_INFO, size)
for i := range buffer {
buffer[i] = CHAR_INFO{WCHAR(' '), attributes}
}
// Write to buffer
r, err := writeConsoleOutput(handle, buffer[:size], windowSize, COORD{X: 0, Y: 0}, &writeRegion)
r, err := writeConsoleOutput(handle, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, &writeRegion)
if !r {
if err != nil {
return 0, err
@@ -437,18 +441,18 @@ func clearDisplayRect(handle uintptr, fillChar rune, attributes WORD, fromCoord
return uint32(size), nil
}
func clearDisplayRange(handle uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (uint32, error) {
func clearDisplayRange(handle uintptr, attributes WORD, fromCoord COORD, toCoord COORD) (uint32, error) {
nw := uint32(0)
// start and end on same line
if fromCoord.Y == toCoord.Y {
return clearDisplayRect(handle, fillChar, attributes, fromCoord, toCoord, windowSize)
return clearDisplayRect(handle, attributes, fromCoord, toCoord)
}
// TODO(azlinux): if full screen, optimize
// spans more than one line
if fromCoord.Y < toCoord.Y {
// from start position till end of line for first line
n, err := clearDisplayRect(handle, fillChar, attributes, fromCoord, COORD{X: windowSize.X - 1, Y: fromCoord.Y}, windowSize)
n, err := clearDisplayRect(handle, attributes, fromCoord, COORD{X: toCoord.X, Y: fromCoord.Y})
if err != nil {
return nw, err
}
@@ -456,14 +460,14 @@ func clearDisplayRange(handle uintptr, fillChar rune, attributes WORD, fromCoord
// lines between
linesBetween := toCoord.Y - fromCoord.Y - 1
if linesBetween > 0 {
n, err = clearDisplayRect(handle, fillChar, attributes, COORD{X: 0, Y: fromCoord.Y + 1}, COORD{X: windowSize.X - 1, Y: toCoord.Y - 1}, windowSize)
n, err = clearDisplayRect(handle, attributes, COORD{X: 0, Y: fromCoord.Y + 1}, COORD{X: toCoord.X, Y: toCoord.Y - 1})
if err != nil {
return nw, err
}
nw += n
}
// lines at end
n, err = clearDisplayRect(handle, fillChar, attributes, COORD{X: 0, Y: toCoord.Y}, toCoord, windowSize)
n, err = clearDisplayRect(handle, attributes, COORD{X: 0, Y: toCoord.Y}, toCoord)
if err != nil {
return nw, err
}
@@ -493,7 +497,7 @@ func setConsoleCursorPosition(handle uintptr, isRelative bool, column int16, lin
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms683207(v=vs.85).aspx
func getNumberOfConsoleInputEvents(handle uintptr) (uint16, error) {
var n WORD
var n DWORD
if err := getError(getNumberOfConsoleInputEventsProc.Call(handle, uintptr(unsafe.Pointer(&n)))); err != nil {
return 0, err
}
@@ -502,7 +506,7 @@ func getNumberOfConsoleInputEvents(handle uintptr) (uint16, error) {
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx
func readConsoleInputKey(handle uintptr, inputBuffer []INPUT_RECORD) (int, error) {
var nr WORD
var nr DWORD
if err := getError(readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&inputBuffer[0])), uintptr(len(inputBuffer)), uintptr(unsafe.Pointer(&nr)))); err != nil {
return 0, err
}
@@ -591,6 +595,7 @@ func (term *WindowsTerminal) HandleOutputCommand(handle uintptr, command []byte)
n = len(command)
parsedCommand := parseAnsiCommand(command)
logrus.Debugf("[windows] HandleOutputCommand: %v", parsedCommand)
// console settings changes need to happen in atomic way
term.outMutex.Lock()
@@ -636,16 +641,17 @@ func (term *WindowsTerminal) HandleOutputCommand(handle uintptr, command []byte)
return n, err
}
if line > int16(screenBufferInfo.Window.Bottom) {
line = int16(screenBufferInfo.Window.Bottom)
line = int16(screenBufferInfo.Window.Bottom) + 1
}
column, err := parseInt16OrDefault(parsedCommand.getParam(1), 1)
if err != nil {
return n, err
}
if column > int16(screenBufferInfo.Window.Right) {
column = int16(screenBufferInfo.Window.Right)
column = int16(screenBufferInfo.Window.Right) + 1
}
// The numbers are not 0 based, but 1 based
logrus.Debugf("[windows] HandleOutputCommmand: Moving cursor to (%v,%v)", column-1, line-1)
if err := setConsoleCursorPosition(handle, false, column-1, line-1); err != nil {
return n, err
}
@@ -713,9 +719,9 @@ func (term *WindowsTerminal) HandleOutputCommand(handle uintptr, command []byte)
switch value {
case 0:
start = screenBufferInfo.CursorPosition
// end of the screen
end.X = screenBufferInfo.MaximumWindowSize.X - 1
end.Y = screenBufferInfo.MaximumWindowSize.Y - 1
// end of the buffer
end.X = screenBufferInfo.Size.X - 1
end.Y = screenBufferInfo.Size.Y - 1
// cursor
cursor = screenBufferInfo.CursorPosition
case 1:
@@ -731,20 +737,21 @@ func (term *WindowsTerminal) HandleOutputCommand(handle uintptr, command []byte)
// start of the screen
start.X = 0
start.Y = 0
// end of the screen
end.X = screenBufferInfo.MaximumWindowSize.X - 1
end.Y = screenBufferInfo.MaximumWindowSize.Y - 1
// end of the buffer
end.X = screenBufferInfo.Size.X - 1
end.Y = screenBufferInfo.Size.Y - 1
// cursor
cursor.X = 0
cursor.Y = 0
}
if _, err := clearDisplayRange(uintptr(handle), ' ', term.screenBufferInfo.Attributes, start, end, screenBufferInfo.MaximumWindowSize); err != nil {
if _, err := clearDisplayRange(uintptr(handle), term.screenBufferInfo.Attributes, start, end); err != nil {
return n, err
}
// remember the the cursor position is 1 based
if err := setConsoleCursorPosition(handle, false, int16(cursor.X), int16(cursor.Y)); err != nil {
return n, err
}
case "K":
// [K
// Clears all characters from the cursor position to the end of the line (including the character at the cursor position).
@@ -764,7 +771,7 @@ func (term *WindowsTerminal) HandleOutputCommand(handle uintptr, command []byte)
// start is where cursor is
start = screenBufferInfo.CursorPosition
// end of line
end.X = screenBufferInfo.MaximumWindowSize.X - 1
end.X = screenBufferInfo.Size.X - 1
end.Y = screenBufferInfo.CursorPosition.Y
// cursor remains the same
cursor = screenBufferInfo.CursorPosition
@@ -780,15 +787,15 @@ func (term *WindowsTerminal) HandleOutputCommand(handle uintptr, command []byte)
case 2:
// start of the line
start.X = 0
start.Y = screenBufferInfo.MaximumWindowSize.Y - 1
start.Y = screenBufferInfo.CursorPosition.Y - 1
// end of the line
end.X = screenBufferInfo.MaximumWindowSize.X - 1
end.Y = screenBufferInfo.MaximumWindowSize.Y - 1
end.X = screenBufferInfo.Size.X - 1
end.Y = screenBufferInfo.CursorPosition.Y - 1
// cursor
cursor.X = 0
cursor.Y = screenBufferInfo.MaximumWindowSize.Y - 1
cursor.Y = screenBufferInfo.CursorPosition.Y - 1
}
if _, err := clearDisplayRange(uintptr(handle), ' ', term.screenBufferInfo.Attributes, start, end, screenBufferInfo.MaximumWindowSize); err != nil {
if _, err := clearDisplayRange(uintptr(handle), term.screenBufferInfo.Attributes, start, end); err != nil {
return n, err
}
// remember the the cursor position is 1 based
@@ -1035,12 +1042,12 @@ func (term *WindowsTerminal) HandleInputSequence(fd uintptr, command []byte) (n
}
func marshal(c COORD) uintptr {
// works only on intel-endian machines
return uintptr(uint32(uint32(uint16(c.Y))<<16 | uint32(uint16(c.X))))
return uintptr(*((*DWORD)(unsafe.Pointer(&c))))
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd uintptr) bool {
// IsConsole returns true if the given file descriptor is a terminal.
// -- The code assumes that GetConsoleMode will return an error for file descriptors that are not a console.
func IsConsole(fd uintptr) bool {
_, e := GetConsoleMode(fd)
return e == nil
}
+16
View File
@@ -1,6 +1,7 @@
package winconsole
import (
"fmt"
"io"
"strconv"
"strings"
@@ -206,6 +207,21 @@ func (c *ansiCommand) getParam(index int) string {
return ""
}
func (ac *ansiCommand) String() string {
return fmt.Sprintf("0x%v \"%v\" (\"%v\")",
bytesToHex(ac.CommandBytes),
ac.Command,
strings.Join(ac.Parameters, "\",\""))
}
func bytesToHex(b []byte) string {
hex := make([]string, len(b))
for i, ch := range b {
hex[i] = fmt.Sprintf("%X", ch)
}
return strings.Join(hex, "")
}
func parseInt16OrDefault(s string, defaultValue int16) (n int16, err error) {
if s == "" {
return defaultValue, nil
@@ -1 +1,2 @@
bundles
nsinit/nsinit
+2
View File
@@ -29,3 +29,5 @@ local:
validate:
hack/validate.sh
binary: all
docker run --rm --privileged -v $(CURDIR)/bundles:/go/bin dockercore/libcontainer make direct-install
+3
View File
@@ -141,6 +141,9 @@ container.Resume()
It is able to spawn new containers or join existing containers. A root
filesystem must be provided for use along with a container configuration file.
To build `nsinit`, run `make binary`. It will save the binary into
`bundles/nsinit`.
To use `nsinit`, cd into a Linux rootfs and copy a `container.json` file into
the directory with your specified configuration. Environment, networking,
and different capabilities for the container are specified in this file.
+1 -14
View File
@@ -217,17 +217,6 @@ profile <profile_name> flags=(attach_disconnected,mediate_deleted) {
file,
umount,
mount fstype=tmpfs,
mount fstype=mqueue,
mount fstype=fuse.*,
mount fstype=binfmt_misc -> /proc/sys/fs/binfmt_misc/,
mount fstype=efivarfs -> /sys/firmware/efi/efivars/,
mount fstype=fusectl -> /sys/fs/fuse/connections/,
mount fstype=securityfs -> /sys/kernel/security/,
mount fstype=debugfs -> /sys/kernel/debug/,
mount fstype=proc -> /proc/,
mount fstype=sysfs -> /sys/,
deny @{PROC}/sys/fs/** wklx,
deny @{PROC}/sysrq-trigger rwklx,
deny @{PROC}/mem rwklx,
@@ -235,9 +224,7 @@ profile <profile_name> flags=(attach_disconnected,mediate_deleted) {
deny @{PROC}/sys/kernel/[^s][^h][^m]* wklx,
deny @{PROC}/sys/kernel/*/** wklx,
deny mount options=(ro, remount) -> /,
deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
deny mount fstype=devpts,
deny mount,
deny /sys/[^f]*/** wklx,
deny /sys/f[^s]*/** wklx,
+1 -14
View File
@@ -27,17 +27,6 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
file,
umount,
mount fstype=tmpfs,
mount fstype=mqueue,
mount fstype=fuse.*,
mount fstype=binfmt_misc -> /proc/sys/fs/binfmt_misc/,
mount fstype=efivarfs -> /sys/firmware/efi/efivars/,
mount fstype=fusectl -> /sys/fs/fuse/connections/,
mount fstype=securityfs -> /sys/kernel/security/,
mount fstype=debugfs -> /sys/kernel/debug/,
mount fstype=proc -> /proc/,
mount fstype=sysfs -> /sys/,
deny @{PROC}/sys/fs/** wklx,
deny @{PROC}/sysrq-trigger rwklx,
deny @{PROC}/mem rwklx,
@@ -45,9 +34,7 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
deny @{PROC}/sys/kernel/[^s][^h][^m]* wklx,
deny @{PROC}/sys/kernel/*/** wklx,
deny mount options=(ro, remount) -> /,
deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
deny mount fstype=devpts,
deny mount,
deny /sys/[^f]*/** wklx,
deny /sys/f[^s]*/** wklx,
@@ -3,7 +3,6 @@
package systemd
import (
"bytes"
"fmt"
"io/ioutil"
"os"
@@ -247,6 +246,21 @@ func writeFile(dir, file, data string) error {
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
}
func join(c *configs.Cgroup, subsystem string, pid int) (string, error) {
path, err := getSubsystemPath(c, subsystem)
if err != nil {
return "", err
}
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
return "", err
}
if err := writeFile(path, "cgroup.procs", strconv.Itoa(pid)); err != nil {
return "", err
}
return path, nil
}
func joinCpu(c *configs.Cgroup, pid int) error {
path, err := getSubsystemPath(c, "cpu")
if err != nil {
@@ -266,16 +280,11 @@ func joinCpu(c *configs.Cgroup, pid int) error {
}
func joinFreezer(c *configs.Cgroup, pid int) error {
path, err := getSubsystemPath(c, "freezer")
if err != nil {
if _, err := join(c, "freezer", pid); err != nil {
return err
}
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
return err
}
return ioutil.WriteFile(filepath.Join(path, "cgroup.procs"), []byte(strconv.Itoa(pid)), 0700)
return nil
}
func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) {
@@ -303,21 +312,15 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
return err
}
if err := ioutil.WriteFile(filepath.Join(path, "freezer.state"), []byte(state), 0); err != nil {
prevState := m.Cgroups.Freezer
m.Cgroups.Freezer = state
freezer := subsystems["freezer"]
err = freezer.Set(path, m.Cgroups)
if err != nil {
m.Cgroups.Freezer = prevState
return err
}
for {
state_, err := ioutil.ReadFile(filepath.Join(path, "freezer.state"))
if err != nil {
return err
}
if string(state) == string(bytes.TrimSpace(state_)) {
break
}
time.Sleep(1 * time.Millisecond)
}
m.Cgroups.Freezer = state
return nil
}
@@ -366,29 +369,16 @@ func getUnitName(c *configs.Cgroup) string {
// because systemd will re-write the device settings if it needs to re-apply the cgroup context.
// This happens at least for v208 when any sibling unit is started.
func joinDevices(c *configs.Cgroup, pid int) error {
path, err := getSubsystemPath(c, "devices")
path, err := join(c, "devices", pid)
if err != nil {
return err
}
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
devices := subsystems["devices"]
if err := devices.Set(path, c); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(path, "cgroup.procs"), []byte(strconv.Itoa(pid)), 0700); err != nil {
return err
}
if !c.AllowAllDevices {
if err := writeFile(path, "devices.deny", "a"); err != nil {
return err
}
}
for _, dev := range c.AllowedDevices {
if err := writeFile(path, "devices.allow", dev.CgroupString()); err != nil {
return err
}
}
return nil
}
@@ -16,6 +16,17 @@ const (
NEWUSER NamespaceType = "NEWUSER"
)
func NamespaceTypes() []NamespaceType {
return []NamespaceType{
NEWNET,
NEWPID,
NEWNS,
NEWUTS,
NEWIPC,
NEWUSER,
}
}
// Namespace defines configuration for each namespace. It specifies an
// alternate path that is able to be joined via setns.
type Namespace struct {
@@ -306,5 +306,11 @@ func (c *linuxContainer) currentState() (*State, error) {
for _, ns := range c.config.Namespaces {
state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid())
}
for _, nsType := range configs.NamespaceTypes() {
if _, ok := state.NamespacePaths[nsType]; !ok {
ns := configs.Namespace{Type: nsType}
state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid())
}
}
return state, nil
}
@@ -130,7 +130,8 @@ func TestGetContainerState(t *testing.T) {
{Type: configs.NEWNS},
{Type: configs.NEWNET, Path: expectedNetworkPath},
{Type: configs.NEWUTS},
{Type: configs.NEWIPC},
// emulate host for IPC
//{Type: configs.NEWIPC},
},
},
initProcess: &mockProcess{
@@ -9,6 +9,7 @@ import (
"testing"
"github.com/docker/libcontainer"
"github.com/docker/libcontainer/cgroups/systemd"
"github.com/docker/libcontainer/configs"
)
@@ -481,6 +482,17 @@ func TestProcessCaps(t *testing.T) {
}
func TestFreeze(t *testing.T) {
testFreeze(t, false)
}
func TestSystemdFreeze(t *testing.T) {
if !systemd.UseSystemd() {
t.Skip("Systemd is unsupported")
}
testFreeze(t, true)
}
func testFreeze(t *testing.T, systemd bool) {
if testing.Short() {
return
}
@@ -497,6 +509,9 @@ func TestFreeze(t *testing.T) {
defer remove(rootfs)
config := newTemplateConfig(rootfs)
if systemd {
config.Cgroups.Slice = "system.slice"
}
factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
if err != nil {
@@ -559,3 +574,77 @@ func TestFreeze(t *testing.T) {
t.Fatal(s.String())
}
}
func TestContainerState(t *testing.T) {
if testing.Short() {
return
}
root, err := newTestRoot()
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(root)
rootfs, err := newRootfs()
if err != nil {
t.Fatal(err)
}
defer remove(rootfs)
l, err := os.Readlink("/proc/1/ns/ipc")
if err != nil {
t.Fatal(err)
}
config := newTemplateConfig(rootfs)
config.Namespaces = configs.Namespaces([]configs.Namespace{
{Type: configs.NEWNS},
{Type: configs.NEWUTS},
// host for IPC
//{Type: configs.NEWIPC},
{Type: configs.NEWPID},
{Type: configs.NEWNET},
})
factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
if err != nil {
t.Fatal(err)
}
container, err := factory.Create("test", config)
if err != nil {
t.Fatal(err)
}
defer container.Destroy()
stdinR, stdinW, err := os.Pipe()
if err != nil {
t.Fatal(err)
}
p := &libcontainer.Process{
Args: []string{"cat"},
Env: standardEnvironment,
Stdin: stdinR,
}
err = container.Start(p)
if err != nil {
t.Fatal(err)
}
stdinR.Close()
defer p.Signal(os.Kill)
st, err := container.State()
if err != nil {
t.Fatal(err)
}
l1, err := os.Readlink(st.NamespacePaths[configs.NEWIPC])
if err != nil {
t.Fatal(err)
}
if l1 != l {
t.Fatal("Container using non-host ipc namespace")
}
stdinW.Close()
p.Wait()
}
@@ -68,9 +68,14 @@ func copyBusybox(dest string) error {
}
func newContainer(config *configs.Config) (libcontainer.Container, error) {
cgm := libcontainer.Cgroupfs
if config.Cgroups != nil && config.Cgroups.Slice == "system.slice" {
cgm = libcontainer.SystemdCgroups
}
factory, err := libcontainer.New(".",
libcontainer.InitArgs(os.Args[0], "init", "--"),
libcontainer.Cgroupfs,
cgm,
)
if err != nil {
return nil, err
+1 -1
View File
@@ -13,7 +13,7 @@ func main() {
app.Version = "2"
app.Author = "libcontainer maintainers"
app.Flags = []cli.Flag{
cli.StringFlag{Name: "root", Value: ".", Usage: "root directory for containers"},
cli.StringFlag{Name: "root", Value: "/var/run/nsinit", Usage: "root directory for containers"},
cli.StringFlag{Name: "log-file", Value: "", Usage: "set the log file to output logs to"},
cli.BoolFlag{Name: "debug", Usage: "enable debug output in the logs"},
}
@@ -119,6 +119,9 @@ func (p *setnsProcess) execSetns() error {
// terminate sends a SIGKILL to the forked process for the setns routine then waits to
// avoid the process becomming a zombie.
func (p *setnsProcess) terminate() error {
if p.cmd.Process == nil {
return nil
}
err := p.cmd.Process.Kill()
if _, werr := p.wait(); err == nil {
err = werr
+41 -8
View File
@@ -11,6 +11,7 @@ import (
"syscall"
"time"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/libcontainer/configs"
"github.com/docker/libcontainer/label"
)
@@ -34,11 +35,6 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
if err := setupPtmx(config, console); err != nil {
return newSystemError(err)
}
// stdin, stdout and stderr could be pointing to /dev/null from parent namespace.
// re-open them inside this namespace.
if err := reOpenDevNull(config.Rootfs); err != nil {
return newSystemError(err)
}
if err := setupDevSymlinks(config.Rootfs); err != nil {
return newSystemError(err)
}
@@ -53,6 +49,9 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) {
if err != nil {
return newSystemError(err)
}
if err := reOpenDevNull(config.Rootfs); err != nil {
return newSystemError(err)
}
if config.Readonlyfs {
if err := setReadonly(); err != nil {
return newSystemError(err)
@@ -105,6 +104,16 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
// unable to bind anything to it.
return err
}
// ensure that the destination of the bind mount is resolved of symlinks at mount time because
// any previous mounts can invalidate the next mount's destination.
// this can happen when a user specifies mounts within other mounts to cause breakouts or other
// evil stuff to try to escape the container's rootfs.
if dest, err = symlink.FollowSymlinkInScope(filepath.Join(rootfs, m.Destination), rootfs); err != nil {
return err
}
if err := checkMountDestination(rootfs, dest); err != nil {
return err
}
if err := createIfNotExists(dest, stat.IsDir()); err != nil {
return err
}
@@ -132,6 +141,28 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
return nil
}
// checkMountDestination checks to ensure that the mount destination is not over the
// top of /proc or /sys.
// dest is required to be an abs path and have any symlinks resolved before calling this function.
func checkMountDestination(rootfs, dest string) error {
if filepath.Clean(rootfs) == filepath.Clean(dest) {
return fmt.Errorf("mounting into / is prohibited")
}
invalidDestinations := []string{
"/proc",
}
for _, invalid := range invalidDestinations {
path, err := filepath.Rel(filepath.Join(rootfs, invalid), dest)
if err != nil {
return err
}
if path == "." || !strings.HasPrefix(path, "..") {
return fmt.Errorf("%q cannot be mounted because it is located inside %q", dest, invalid)
}
}
return nil
}
func setupDevSymlinks(rootfs string) error {
var links = [][2]string{
{"/proc/self/fd", "/dev/fd"},
@@ -156,11 +187,13 @@ func setupDevSymlinks(rootfs string) error {
return nil
}
// If stdin, stdout or stderr are pointing to '/dev/null' in the global mount namespace,
// this method will make them point to '/dev/null' in this namespace.
// If stdin, stdout, and/or stderr are pointing to `/dev/null` in the parent's rootfs
// this method will make them point to `/dev/null` in this container's rootfs. This
// needs to be called after we chroot/pivot into the container's rootfs so that any
// symlinks are resolved locally.
func reOpenDevNull(rootfs string) error {
var stat, devNullStat syscall.Stat_t
file, err := os.Open(filepath.Join(rootfs, "/dev/null"))
file, err := os.Open("/dev/null")
if err != nil {
return fmt.Errorf("Failed to open /dev/null - %s", err)
}
@@ -0,0 +1,37 @@
// +build linux
package libcontainer
import "testing"
func TestCheckMountDestOnProc(t *testing.T) {
dest := "/rootfs/proc/"
err := checkMountDestination("/rootfs", dest)
if err == nil {
t.Fatal("destination inside proc should return an error")
}
}
func TestCheckMountDestInSys(t *testing.T) {
dest := "/rootfs//sys/fs/cgroup"
err := checkMountDestination("/rootfs", dest)
if err != nil {
t.Fatal("destination inside /sys should not return an error")
}
}
func TestCheckMountDestFalsePositive(t *testing.T) {
dest := "/rootfs/sysfiles/fs/cgroup"
err := checkMountDestination("/rootfs", dest)
if err != nil {
t.Fatal(err)
}
}
func TestCheckMountRoot(t *testing.T) {
dest := "/rootfs"
err := checkMountDestination("/rootfs", dest)
if err == nil {
t.Fatal(err)
}
}