mirror of
https://github.com/clearlinux/docker.git
synced 2026-08-19 12:16:30 +00:00
Compare commits
23 Commits
v1.6.0-rc4
...
v1.6.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 47496519da | |||
| fdd21bf032 | |||
| d928dad8c8 | |||
| 82366ce059 | |||
| 6410c3c066 | |||
| 9231dc9cc0 | |||
| 6a3f37386b | |||
| d9a0c05208 | |||
| 24cb9df189 | |||
| c51cd3298c | |||
| 10affa8018 | |||
| ce27fa2716 | |||
| 8d83409e85 | |||
| 3a73b6a2bf | |||
| f99269882f | |||
| 568a9703ac | |||
| faaeb5162d | |||
| b5613baac2 | |||
| c956efcd52 | |||
| 5455864187 | |||
| ceb72fab34 | |||
| c6ea062a26 | |||
| 0e045ab50c |
@@ -1,5 +1,25 @@
|
||||
# Changelog
|
||||
|
||||
## 1.6.0 (2015-04-07)
|
||||
|
||||
#### Builder
|
||||
+ Building images from an image ID
|
||||
+ 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
|
||||
|
||||
#### Runtime
|
||||
+ Container and image Labels
|
||||
+ `--cgroup-parent` for specifying a parent cgroup to place container cgroup within
|
||||
+ Logging drivers, `json-file`, `syslog`, or `none`
|
||||
+ Pulling images by ID
|
||||
+ `--ulimit` to set the ulimit on a container
|
||||
+ `--default-ulimit` option on the daemon which applies to all created containers (and overwritten by `--ulimit` on run)
|
||||
|
||||
## 1.5.0 (2015-02-10)
|
||||
|
||||
#### Builder
|
||||
|
||||
+3
-3
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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>
|
||||
|
||||
|
||||
@@ -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
@@ -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', ' ▪ Deploy a registry' ]
|
||||
- ['registry/configuration.md', 'Reference', ' ▪ Configure a registry' ]
|
||||
- ['registry/storagedrivers.md', 'Reference', ' ▪ Storage driver model' ]
|
||||
- ['registry/notifications.md', 'Reference', ' ▪ Work with notifications' ]
|
||||
- ['registry/spec/api.md', 'Reference', ' ▪ Registry Service API v2' ]
|
||||
- ['registry/spec/json.md', 'Reference', ' ▪ JSON format' ]
|
||||
- ['registry/spec/auth/token.md', 'Reference', ' ▪ Authenticate via central service' ]
|
||||
- ['reference/api/hub_registry_spec.md', 'Reference', 'Docker Hub and Registry 1.0']
|
||||
- ['reference/api/registry_api.md', 'Reference', ' ▪ Docker Registry API v1']
|
||||
- ['reference/api/registry_api_client_libraries.md', 'Reference', ' ▪ 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
@@ -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() {
|
||||
|
||||
@@ -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/" } }
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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
@@ -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
@@ -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 bd8ec36106086f72b66e1be85a81202b93503e44
|
||||
# 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')"
|
||||
|
||||
@@ -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,28 @@ 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")
|
||||
}
|
||||
|
||||
+59
-58
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
+27
-37
@@ -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
|
||||
|
||||
@@ -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"},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user