summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RELEASE_NOTES.md26
-rw-r--r--cmd/podman/common.go2
-rw-r--r--docs/source/markdown/podman-create.1.md3
-rw-r--r--docs/source/markdown/podman-exec.1.md2
-rw-r--r--docs/source/markdown/podman-rmi.1.md2
-rw-r--r--docs/source/markdown/podman-run.1.md3
-rw-r--r--libpod/container.go5
-rw-r--r--libpod/oci_conmon_linux.go13
-rw-r--r--libpod/options.go21
-rw-r--r--pkg/api/Makefile10
-rw-r--r--pkg/api/handlers/handler.go16
-rw-r--r--pkg/api/handlers/images_build.go229
-rw-r--r--pkg/api/server/register_images.go205
-rw-r--r--pkg/api/server/server.go22
-rw-r--r--pkg/rootless/rootless_linux.c9
-rw-r--r--pkg/spec/namespaces.go4
-rw-r--r--pkg/spec/spec.go4
-rw-r--r--pkg/systemdgen/systemdgen.go5
-rw-r--r--pkg/systemdgen/systemdgen_test.go2
19 files changed, 444 insertions, 139 deletions
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 7864b9232..0ef3e4322 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,31 @@
# Release Notes
+## 1.7.1
+### Features
+- Rootless Podman now uses Rootlesskit for port forwarding, which should greatly improve performance and capabilities
+- The `podman untag` command has been added to remove tags from images without deleting them
+- The `podman service` command has been added to run an API server for managing Podman remotely
+- The `podman inspect` command on images now displays previous names they used
+- The `podman generate systemd` command now supports a `--new` option to generate service files that create and run new containers instead of managing existing containers
+- Support for `--log-opt tag=` to set logging tags has been added to the `journald` log driver
+- Added support for using Seccomp profiles embedded in images for `podman run` and `podman create` via the new `--seccomp-policy` CLI flag ([#4806](https://github.com/containers/libpod/pull/4806))
+
+### Bugfixes
+- Fixed a bug where the `podman cp` command would not copy the contents of directories when paths ending in `/.` were given ([#4717](https://github.com/containers/libpod/issues/4717))
+- Fixed a bug where the `podman play kube` command did not properly locate Seccomp profiles specified relative to localhost ([#4555](https://github.com/containers/libpod/issues/4555))
+- Fixed a bug where the `podman info` command for remote Podman did not show registry information ([#4793](https://github.com/containers/libpod/issues/4793))
+- Fixed a bug where the `podman exec` command did not support having input piped into it ([#3302](https://github.com/containers/libpod/issues/3302))
+- Fixed a bug where the `podman cp` command with rootless Podman on CGroups v2 systems did not properly determine if the container could be paused while copying ([#4813](https://github.com/containers/libpod/issues/4813))
+- Fixed a bug where the `podman container prune --force` command could possible remove running containers if they were started while the command was running ([#4844](https://github.com/containers/libpod/issues/4844))
+- Fixed a bug where Podman, when run as root, would not properly configure `slirp4netns` networking when requested ([#4853](https://github.com/containers/libpod/pull/4853))
+- Fixed a bug where `podman run --userns=keep-id` did not work when the user had a UID over 65535 ([#4838](https://github.com/containers/libpod/issues/4838))
+- Fixed a bug where rootless `podman run` and `podman create` with the `--userns=keep-id` option could change permissions on `/run/user/$UID` and break KDE ([#4846](https://github.com/containers/libpod/issues/4846))
+
+### Misc
+- Initial work on version 2 of the Podman remote API has been merged, but is still in an alpha state and not ready for use. Read more [here](https://podman.io/releases/2020/01/17/podman-new-api.html)
+- Updated vendored Buildah to v1.13.1
+- Updated vendored containers/storage to v1.15.5
+
## 1.7.0
### Features
- Added support for setting a static MAC address for containers
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 8690be64f..f3aff1d49 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -158,7 +158,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
)
createFlags.String(
"cgroups", "enabled",
- "control container cgroup configuration",
+ `control container cgroup configuration ("enabled"|"disabled"|"no-conmon")`,
)
createFlags.String(
"cgroup-parent", "",
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 0236e30ba..7f0c2260c 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -78,8 +78,9 @@ If the host uses cgroups v1, the default is set to **host**. On cgroups v2 the
**--cgroups**=*mode*
Determines whether the container will create CGroups.
-Valid values are *enabled* and *disabled*, which the default being *enabled*.
+Valid values are *enabled*, *disabled*, *no-conmon*, which the default being *enabled*.
The *disabled* option will force the container to not create CGroups, and thus conflicts with CGroup options (**--cgroupns** and **--cgroup-parent**).
+The *no-conmon* option disables a new CGroup only for the conmon process.
**--cgroup-parent**=*path*
diff --git a/docs/source/markdown/podman-exec.1.md b/docs/source/markdown/podman-exec.1.md
index fc67211d1..8c0106d70 100644
--- a/docs/source/markdown/podman-exec.1.md
+++ b/docs/source/markdown/podman-exec.1.md
@@ -105,9 +105,11 @@ non-zero code, the exit codes follow the `chroot` standard, see below:
## EXAMPLES
+```
$ podman exec -it ctrID ls
$ podman exec -it -w /tmp myCtr pwd
$ podman exec --user root ctrID ls
+```
## SEE ALSO
podman(1), podman-run(1)
diff --git a/docs/source/markdown/podman-rmi.1.md b/docs/source/markdown/podman-rmi.1.md
index d911ee6cb..3c46bc32c 100644
--- a/docs/source/markdown/podman-rmi.1.md
+++ b/docs/source/markdown/podman-rmi.1.md
@@ -29,7 +29,7 @@ podman rmi c0ed59d05ff7
Remove an image and its associated containers.
```
podman rmi --force imageID
-````
+```
Remove multiple images by their shortened IDs.
```
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index f613e6668..2b1452b53 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -92,8 +92,9 @@ If the host uses cgroups v1, the default is set to **host**. On cgroups v2 the
**--cgroups**=*mode*
Determines whether the container will create CGroups.
-Valid values are *enabled* and *disabled*, which the default being *enabled*.
+Valid values are *enabled*, *disabled*, *no-conmon*, which the default being *enabled*.
The *disabled* option will force the container to not create CGroups, and thus conflicts with CGroup options (**--cgroupns** and **--cgroup-parent**).
+The *no-conmon* option disables a new CGroup only for the conmon process.
**--cgroup-parent**=*cgroup*
diff --git a/libpod/container.go b/libpod/container.go
index b3cb6334a..f29cebf20 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -373,8 +373,11 @@ type ContainerConfig struct {
// Time container was created
CreatedTime time.Time `json:"createdTime"`
// NoCgroups indicates that the container will not create CGroups. It is
- // incompatible with CgroupParent.
+ // incompatible with CgroupParent. Deprecated in favor of CgroupsMode.
NoCgroups bool `json:"noCgroups,omitempty"`
+ // CgroupsMode indicates how the container will create cgroups
+ // (disabled, no-conmon, enabled). It supersedes NoCgroups.
+ CgroupsMode string `json:"cgroupsMode,omitempty"`
// Cgroup parent of the container
CgroupParent string `json:"cgroupParent"`
// LogPath log location
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index 0e8a64865..722012386 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -1425,11 +1425,22 @@ func startCommandGivenSelinux(cmd *exec.Cmd) error {
// it then signals for conmon to start by sending nonse data down the start fd
func (r *ConmonOCIRuntime) moveConmonToCgroupAndSignal(ctr *Container, cmd *exec.Cmd, startFd *os.File) error {
mustCreateCgroup := true
- // If cgroup creation is disabled - just signal.
+
if ctr.config.NoCgroups {
mustCreateCgroup = false
}
+ // If cgroup creation is disabled - just signal.
+ switch ctr.config.CgroupsMode {
+ case "disabled", "no-conmon":
+ mustCreateCgroup = false
+ }
+
+ // $INVOCATION_ID is set by systemd when running as a service.
+ if os.Getenv("INVOCATION_ID") != "" {
+ mustCreateCgroup = false
+ }
+
if mustCreateCgroup {
cgroupParent := ctr.CgroupParent()
if r.cgroupManager == define.SystemdCgroupsManager {
diff --git a/libpod/options.go b/libpod/options.go
index 8bc5a541d..593037382 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1078,25 +1078,26 @@ func WithLogTag(tag string) CtrCreateOption {
}
-// WithNoCgroups disables the creation of CGroups for the new container.
-func WithNoCgroups() CtrCreateOption {
+// WithCgroupsMode disables the creation of CGroups for the conmon process.
+func WithCgroupsMode(mode string) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return define.ErrCtrFinalized
}
- if ctr.config.CgroupParent != "" {
- return errors.Wrapf(define.ErrInvalidArg, "NoCgroups conflicts with CgroupParent")
- }
-
- if ctr.config.PIDNsCtr != "" {
- return errors.Wrapf(define.ErrInvalidArg, "NoCgroups requires a private PID namespace and cannot be used when PID namespace is shared with another container")
+ switch mode {
+ case "disabled":
+ ctr.config.NoCgroups = true
+ ctr.config.CgroupsMode = mode
+ case "enabled", "no-conmon":
+ ctr.config.CgroupsMode = mode
+ default:
+ return errors.Wrapf(define.ErrInvalidArg, "Invalid cgroup mode %q", mode)
}
- ctr.config.NoCgroups = true
-
return nil
}
+
}
// WithCgroupParent sets the Cgroup Parent of the new container.
diff --git a/pkg/api/Makefile b/pkg/api/Makefile
index 8a1556800..915f0b9b3 100644
--- a/pkg/api/Makefile
+++ b/pkg/api/Makefile
@@ -2,6 +2,12 @@ export GO111MODULE=off
SWAGGER_OUT ?= swagger.yaml
-swagger:
+.PHONY: ${SWAGGER_OUT}
+${SWAGGER_OUT}:
+ # generate doesn't remove file on error
+ rm -f ${SWAGGER_OUT}
swagger generate spec -o ${SWAGGER_OUT} -w ./
- cat tags.yaml >> swagger.yaml
+
+# TODO: when pass validation move it under swagger.
+validate:
+ swagger validate ${SWAGGER_OUT}
diff --git a/pkg/api/handlers/handler.go b/pkg/api/handlers/handler.go
index 2efeb1379..4f303f6ab 100644
--- a/pkg/api/handlers/handler.go
+++ b/pkg/api/handlers/handler.go
@@ -36,11 +36,11 @@ func getRuntime(r *http.Request) *libpod.Runtime {
return r.Context().Value("runtime").(*libpod.Runtime)
}
-func getHeader(r *http.Request, k string) string {
- return r.Header.Get(k)
-}
-
-func hasHeader(r *http.Request, k string) bool {
- _, found := r.Header[k]
- return found
-}
+// func getHeader(r *http.Request, k string) string {
+// return r.Header.Get(k)
+// }
+//
+// func hasHeader(r *http.Request, k string) bool {
+// _, found := r.Header[k]
+// return found
+// }
diff --git a/pkg/api/handlers/images_build.go b/pkg/api/handlers/images_build.go
index c7c746392..b29c45574 100644
--- a/pkg/api/handlers/images_build.go
+++ b/pkg/api/handlers/images_build.go
@@ -1,6 +1,7 @@
package handlers
import (
+ "bytes"
"encoding/base64"
"encoding/json"
"fmt"
@@ -9,58 +10,66 @@ import (
"net/http"
"os"
"path/filepath"
+ "strconv"
"strings"
"github.com/containers/buildah"
"github.com/containers/buildah/imagebuildah"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/storage/pkg/archive"
- log "github.com/sirupsen/logrus"
+ "github.com/gorilla/mux"
)
func BuildImage(w http.ResponseWriter, r *http.Request) {
authConfigs := map[string]AuthConfig{}
- if hasHeader(r, "X-Registry-Config") {
- registryHeader := getHeader(r, "X-Registry-Config")
- authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(registryHeader))
+ if hdr, found := r.Header["X-Registry-Config"]; found && len(hdr) > 0 {
+ authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(hdr[0]))
if json.NewDecoder(authConfigsJSON).Decode(&authConfigs) != nil {
- utils.BadRequest(w, "X-Registry-Config", registryHeader, json.NewDecoder(authConfigsJSON).Decode(&authConfigs))
+ utils.BadRequest(w, "X-Registry-Config", hdr[0], json.NewDecoder(authConfigsJSON).Decode(&authConfigs))
return
}
}
+ if hdr, found := r.Header["Content-Type"]; found && len(hdr) > 0 {
+ if hdr[0] != "application/x-tar" {
+ utils.BadRequest(w, "Content-Type", hdr[0],
+ fmt.Errorf("Content-Type: %s is not supported. Should be \"application/x-tar\"", hdr[0]))
+ }
+ }
+
anchorDir, err := extractTarFile(r, w)
if err != nil {
utils.InternalServerError(w, err)
return
}
- // defer os.RemoveAll(anchorDir)
+ defer os.RemoveAll(anchorDir)
query := struct {
- Dockerfile string `json:"dockerfile"`
- Tag string `json:"t"`
- ExtraHosts string `json:"extrahosts"`
- Remote string `json:"remote"`
- Quiet bool `json:"q"`
- NoCache bool `json:"nocache"`
- CacheFrom string `json:"cachefrom"`
- Pull string `json:"pull"`
- Rm bool `json:"rm"`
- ForceRm bool `json:"forcerm"`
- Memory int `json:"memory"`
- MemSwap int `json:"memswap"`
- CpuShares int `json:"cpushares"`
- CpuSetCpus string `json:"cpusetcpus"`
- CpuPeriod int `json:"cpuperiod"`
- CpuQuota int `json:"cpuquota"`
- BuildArgs string `json:"buildargs"`
- ShmSize int `json:"shmsize"`
- Squash bool `json:"squash"`
- Labels string `json:"labels"`
- NetworkMode string `json:"networkmode"`
- Platform string `json:"platform"`
- Target string `json:"target"`
- Outputs string `json:"outputs"`
+ Dockerfile string `schema:"dockerfile"`
+ Tag string `schema:"t"`
+ ExtraHosts string `schema:"extrahosts"`
+ Remote string `schema:"remote"`
+ Quiet bool `schema:"q"`
+ NoCache bool `schema:"nocache"`
+ CacheFrom string `schema:"cachefrom"`
+ Pull bool `schema:"pull"`
+ Rm bool `schema:"rm"`
+ ForceRm bool `schema:"forcerm"`
+ Memory int64 `schema:"memory"`
+ MemSwap int64 `schema:"memswap"`
+ CpuShares uint64 `schema:"cpushares"`
+ CpuSetCpus string `schema:"cpusetcpus"`
+ CpuPeriod uint64 `schema:"cpuperiod"`
+ CpuQuota int64 `schema:"cpuquota"`
+ BuildArgs string `schema:"buildargs"`
+ ShmSize int `schema:"shmsize"`
+ Squash bool `schema:"squash"`
+ Labels string `schema:"labels"`
+ NetworkMode string `schema:"networkmode"`
+ Platform string `schema:"platform"`
+ Target string `schema:"target"`
+ Outputs string `schema:"outputs"`
+ Registry string `schema:"registry"`
}{
Dockerfile: "Dockerfile",
Tag: "",
@@ -69,7 +78,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Quiet: false,
NoCache: false,
CacheFrom: "",
- Pull: "",
+ Pull: false,
Rm: true,
ForceRm: false,
Memory: 0,
@@ -86,6 +95,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Platform: "",
Target: "",
Outputs: "",
+ Registry: "docker.io",
}
if err := decodeQuery(r, &query); err != nil {
@@ -93,80 +103,121 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
return
}
- // Tag is the name with optional tag...
- var name = query.Tag
- var tag string
+ var (
+ // Tag is the name with optional tag...
+ name = query.Tag
+ tag = "latest"
+ )
if strings.Contains(query.Tag, ":") {
tokens := strings.SplitN(query.Tag, ":", 2)
name = tokens[0]
tag = tokens[1]
}
+ if t, found := mux.Vars(r)["target"]; found {
+ name = t
+ }
+
var buildArgs = map[string]string{}
- if found := hasVar(r, "buildargs"); found {
- if err := json.Unmarshal([]byte(query.BuildArgs), &buildArgs); err != nil {
- utils.BadRequest(w, "buildargs", query.BuildArgs, err)
+ if a, found := mux.Vars(r)["buildargs"]; found {
+ if err := json.Unmarshal([]byte(a), &buildArgs); err != nil {
+ utils.BadRequest(w, "buildargs", a, err)
return
}
}
// convert label formats
var labels = []string{}
- if hasVar(r, "labels") {
+ if l, found := mux.Vars(r)["labels"]; found {
var m = map[string]string{}
- if err := json.Unmarshal([]byte(query.Labels), &m); err != nil {
- utils.BadRequest(w, "labels", query.Labels, err)
+ if err := json.Unmarshal([]byte(l), &m); err != nil {
+ utils.BadRequest(w, "labels", l, err)
return
}
for k, v := range m {
- labels = append(labels, fmt.Sprintf("%s=%v", k, v))
+ labels = append(labels, k+"="+v)
+ }
+ }
+
+ pullPolicy := buildah.PullIfMissing
+ if _, found := mux.Vars(r)["pull"]; found {
+ if query.Pull {
+ pullPolicy = buildah.PullAlways
}
}
+ // build events will be recorded here
+ var (
+ buildEvents = []string{}
+ progress = bytes.Buffer{}
+ )
+
buildOptions := imagebuildah.BuildOptions{
ContextDirectory: filepath.Join(anchorDir, "build"),
- PullPolicy: 0,
- Registry: "",
- IgnoreUnrecognizedInstructions: false,
+ PullPolicy: pullPolicy,
+ Registry: query.Registry,
+ IgnoreUnrecognizedInstructions: true,
Quiet: query.Quiet,
- Isolation: 0,
+ Isolation: buildah.IsolationChroot,
Runtime: "",
RuntimeArgs: nil,
TransientMounts: nil,
- Compression: 0,
+ Compression: archive.Gzip,
Args: buildArgs,
Output: name,
AdditionalTags: []string{tag},
- Log: nil,
- In: nil,
- Out: nil,
- Err: nil,
- SignaturePolicyPath: "",
- ReportWriter: nil,
- OutputFormat: "",
- SystemContext: nil,
- NamespaceOptions: nil,
- ConfigureNetwork: 0,
- CNIPluginPath: "",
- CNIConfigDir: "",
- IDMappingOptions: nil,
- AddCapabilities: nil,
- DropCapabilities: nil,
- CommonBuildOpts: &buildah.CommonBuildOptions{},
- DefaultMountsFilePath: "",
- IIDFile: "",
- Squash: query.Squash,
- Labels: labels,
- Annotations: nil,
- OnBuild: nil,
- Layers: false,
- NoCache: query.NoCache,
- RemoveIntermediateCtrs: query.Rm,
- ForceRmIntermediateCtrs: query.ForceRm,
- BlobDirectory: "",
- Target: query.Target,
- Devices: nil,
+ Log: func(format string, args ...interface{}) {
+ buildEvents = append(buildEvents, fmt.Sprintf(format, args...))
+ },
+ In: nil,
+ Out: &progress,
+ Err: &progress,
+ SignaturePolicyPath: "",
+ ReportWriter: &progress,
+ OutputFormat: buildah.Dockerv2ImageManifest,
+ SystemContext: nil,
+ NamespaceOptions: nil,
+ ConfigureNetwork: 0,
+ CNIPluginPath: "",
+ CNIConfigDir: "",
+ IDMappingOptions: nil,
+ AddCapabilities: nil,
+ DropCapabilities: nil,
+ CommonBuildOpts: &buildah.CommonBuildOptions{
+ AddHost: nil,
+ CgroupParent: "",
+ CPUPeriod: query.CpuPeriod,
+ CPUQuota: query.CpuQuota,
+ CPUShares: query.CpuShares,
+ CPUSetCPUs: query.CpuSetCpus,
+ CPUSetMems: "",
+ HTTPProxy: false,
+ Memory: query.Memory,
+ DNSSearch: nil,
+ DNSServers: nil,
+ DNSOptions: nil,
+ MemorySwap: query.MemSwap,
+ LabelOpts: nil,
+ SeccompProfilePath: "",
+ ApparmorProfile: "",
+ ShmSize: strconv.Itoa(query.ShmSize),
+ Ulimit: nil,
+ Volumes: nil,
+ },
+ DefaultMountsFilePath: "",
+ IIDFile: "",
+ Squash: query.Squash,
+ Labels: labels,
+ Annotations: nil,
+ OnBuild: nil,
+ Layers: false,
+ NoCache: query.NoCache,
+ RemoveIntermediateCtrs: query.Rm,
+ ForceRmIntermediateCtrs: query.ForceRm,
+ BlobDirectory: "",
+ Target: query.Target,
+ Devices: nil,
}
id, _, err := getRuntime(r).Build(r.Context(), buildOptions, query.Dockerfile)
@@ -179,17 +230,13 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
struct {
Stream string `json:"stream"`
}{
- Stream: fmt.Sprintf("Successfully built %s\n", id),
+ Stream: progress.String() + "\n" +
+ strings.Join(buildEvents, "\n") +
+ fmt.Sprintf("\nSuccessfully built %s\n", id),
})
}
func extractTarFile(r *http.Request, w http.ResponseWriter) (string, error) {
- var (
- // length int64
- // n int64
- copyErr error
- )
-
// build a home for the request body
anchorDir, err := ioutil.TempDir("", "libpod_builder")
if err != nil {
@@ -204,26 +251,14 @@ func extractTarFile(r *http.Request, w http.ResponseWriter) (string, error) {
}
defer tarBall.Close()
- // if hasHeader(r, "Content-Length") {
- // length, err := strconv.ParseInt(getHeader(r, "Content-Length"), 10, 64)
- // if err != nil {
- // return "", errors.New(fmt.Sprintf("Failed request: unable to parse Content-Length of '%s'", getHeader(r, "Content-Length")))
- // }
- // n, copyErr = io.CopyN(tarBall, r.Body, length+1)
- // } else {
- _, copyErr = io.Copy(tarBall, r.Body)
- // }
+ // Content-Length not used as too many existing API clients didn't honor it
+ _, err = io.Copy(tarBall, r.Body)
r.Body.Close()
- if copyErr != nil {
+ if err != nil {
utils.InternalServerError(w,
fmt.Errorf("failed Request: Unable to copy tar file from request body %s", r.RequestURI))
}
- log.Debugf("Content-Length: %s", getVar(r, "Content-Length"))
-
- // if hasHeader(r, "Content-Length") && n != length {
- // return "", errors.New(fmt.Sprintf("Failed request: Given Content-Length does not match file size %d != %d", n, length))
- // }
_, _ = tarBall.Seek(0, 0)
if err := archive.Untar(tarBall, buildDir, &archive.TarOptions{}); err != nil {
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 7f1bb4e5c..8ea079654 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -342,6 +342,210 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/commit"), APIHandler(s.Context, generic.CommitContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /build images buildImage
+ // ---
+ // tags:
+ // - images
+ // summary: Create image
+ // description: Build an image from the given Dockerfile(s)
+ // parameters:
+ // - in: query
+ // name: dockerfile
+ // type: string
+ // default: Dockerfile
+ // description: |
+ // Path within the build context to the `Dockerfile`.
+ // This is ignored if remote is specified and points to an external `Dockerfile`.
+ // - in: query
+ // name: t
+ // type: string
+ // default: latest
+ // description: A name and optional tag to apply to the image in the `name:tag` format.
+ // - in: query
+ // name: extrahosts
+ // type: string
+ // default:
+ // description: |
+ // TBD Extra hosts to add to /etc/hosts
+ // (As of version 1.xx)
+ // - in: query
+ // name: remote
+ // type: string
+ // default:
+ // description: |
+ // A Git repository URI or HTTP/HTTPS context URI.
+ // If the URI points to a single text file, the file’s contents are placed
+ // into a file called Dockerfile and the image is built from that file. If
+ // the URI points to a tarball, the file is downloaded by the daemon and the
+ // contents therein used as the context for the build. If the URI points to a
+ // tarball and the dockerfile parameter is also specified, there must be a file
+ // with the corresponding path inside the tarball.
+ // (As of version 1.xx)
+ // - in: query
+ // name: q
+ // type: boolean
+ // default: false
+ // description: |
+ // Suppress verbose build output
+ // - in: query
+ // name: nocache
+ // type: boolean
+ // default: false
+ // description: |
+ // Do not use the cache when building the image
+ // (As of version 1.xx)
+ // - in: query
+ // name: cachefrom
+ // type: string
+ // default:
+ // description: |
+ // JSON array of images used to build cache resolution
+ // (As of version 1.xx)
+ // - in: query
+ // name: pull
+ // type: boolean
+ // default: false
+ // description: |
+ // Attempt to pull the image even if an older image exists locally
+ // (As of version 1.xx)
+ // - in: query
+ // name: rm
+ // type: boolean
+ // default: true
+ // description: |
+ // Remove intermediate containers after a successful build
+ // (As of version 1.xx)
+ // - in: query
+ // name: forcerm
+ // type: boolean
+ // default: false
+ // description: |
+ // Always remove intermediate containers, even upon failure
+ // (As of version 1.xx)
+ // - in: query
+ // name: memory
+ // type: integer
+ // description: |
+ // Memory is the upper limit (in bytes) on how much memory running containers can use
+ // (As of version 1.xx)
+ // - in: query
+ // name: memswap
+ // type: integer
+ // description: |
+ // MemorySwap limits the amount of memory and swap together
+ // (As of version 1.xx)
+ // - in: query
+ // name: cpushares
+ // type: integer
+ // description: |
+ // CPUShares (relative weight
+ // (As of version 1.xx)
+ // - in: query
+ // name: cpusetcpus
+ // type: string
+ // description: |
+ // CPUSetCPUs in which to allow execution (0-3, 0,1)
+ // (As of version 1.xx)
+ // - in: query
+ // name: cpuperiod
+ // type: integer
+ // description: |
+ // CPUPeriod limits the CPU CFS (Completely Fair Scheduler) period
+ // (As of version 1.xx)
+ // - in: query
+ // name: cpuquota
+ // type: integer
+ // description: |
+ // CPUQuota limits the CPU CFS (Completely Fair Scheduler) quota
+ // (As of version 1.xx)
+ // - in: query
+ // name: buildargs
+ // type: string
+ // default:
+ // description: |
+ // JSON map of string pairs denoting build-time variables.
+ // For example, the build argument `Foo` with the value of `bar` would be encoded in JSON as `["Foo":"bar"]`.
+ //
+ // For example, buildargs={"Foo":"bar"}.
+ //
+ // Note(s):
+ // * This should not be used to pass secrets.
+ // * The value of buildargs should be URI component encoded before being passed to the API.
+ //
+ // (As of version 1.xx)
+ // - in: query
+ // name: shmsize
+ // type: integer
+ // default: 67108864
+ // description: |
+ // ShmSize is the "size" value to use when mounting an shmfs on the container's /dev/shm directory.
+ // Default is 64MB
+ // (As of version 1.xx)
+ // - in: query
+ // name: squash
+ // type: boolean
+ // default: false
+ // description: |
+ // Silently ignored.
+ // Squash the resulting images layers into a single layer
+ // (As of version 1.xx)
+ // - in: query
+ // name: labels
+ // type: string
+ // default:
+ // description: |
+ // JSON map of key, value pairs to set as labels on the new image
+ // (As of version 1.xx)
+ // - in: query
+ // name: networkmode
+ // type: string
+ // default: bridge
+ // description: |
+ // Sets the networking mode for the run commands during build.
+ // Supported standard values are:
+ // * `bridge` limited to containers within a single host, port mapping required for external access
+ // * `host` no isolation between host and containers on this network
+ // * `none` disable all networking for this container
+ // * container:<nameOrID> share networking with given container
+ // ---All other values are assumed to be a custom network's name
+ // (As of version 1.xx)
+ // - in: query
+ // name: platform
+ // type: string
+ // default:
+ // description: |
+ // Platform format os[/arch[/variant]]
+ // (As of version 1.xx)
+ // - in: query
+ // name: target
+ // type: string
+ // default:
+ // description: |
+ // Target build stage
+ // (As of version 1.xx)
+ // - in: query
+ // name: outputs
+ // type: string
+ // default:
+ // description: |
+ // output configuration TBD
+ // (As of version 1.xx)
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // description: OK (As of version 1.xx)
+ // schema:
+ // type: object
+ // required:
+ // - stream
+ // properties:
+ // stream:
+ // type: string
+ // example: |
+ // (build details...)
+ // Successfully built 8ba084515c724cbf90d447a63600c0a6
+ r.Handle(VersionedPath("/build"), APIHandler(s.Context, handlers.BuildImage)).Methods(http.MethodPost)
/*
libpod endpoints
*/
@@ -603,6 +807,5 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/{name:..*}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost)
- r.Handle(VersionedPath("/build"), APIHandler(s.Context, handlers.BuildImage)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index f3bae0345..69a44f21a 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -1,6 +1,6 @@
-// Package serviceapi Provides a Container compatible interface (EXPERIMENTAL)
+// Package api Provides a container compatible interface.
//
-// This documentation describes the HTTP LibPod interface. It is to be consider
+// This documentation describes the HTTP Libpod interface. It is to be consider
// only as experimental as this point. The endpoints, parameters, inputs, and
// return values can all change.
//
@@ -25,12 +25,18 @@
// - text/html
//
// tags:
-// - name: "Containers"
-// description: manage containers
-// - name: "Images"
-// description: manage images
-// - name: "System"
-// description: manage system resources
+// - name: containers
+// description: Actions related to containers
+// - name: images
+// description: Actions related to images
+// - name: pods
+// description: Actions related to pods
+// - name: volumes
+// description: Actions related to volumes
+// - name: containers (compat)
+// description: Actions related to containers for the compatibility endpoints
+// - name: images (compat)
+// description: Actions related to images for the compatibility endpoints
//
// swagger:meta
package server
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 193c788c0..041a161dc 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -266,6 +266,8 @@ static void __attribute__((constructor)) init()
char path[PATH_MAX];
const char *const suffix = "/libpod/pause.pid";
char *cwd = getcwd (NULL, 0);
+ char uid_fmt[16];
+ char gid_fmt[16];
if (cwd == NULL)
{
@@ -324,6 +326,13 @@ static void __attribute__((constructor)) init()
exit (EXIT_FAILURE);
}
+ sprintf (uid_fmt, "%d", uid);
+ sprintf (gid_fmt, "%d", gid);
+
+ setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1);
+ setenv ("_CONTAINERS_ROOTLESS_UID", uid_fmt, 1);
+ setenv ("_CONTAINERS_ROOTLESS_GID", gid_fmt, 1);
+
r = setns (fd, 0);
if (r < 0)
{
diff --git a/pkg/spec/namespaces.go b/pkg/spec/namespaces.go
index e62d4ed0a..1f98e6e25 100644
--- a/pkg/spec/namespaces.go
+++ b/pkg/spec/namespaces.go
@@ -213,8 +213,8 @@ func (c *CgroupConfig) ToCreateOptions(runtime *libpod.Runtime) ([]libpod.CtrCre
options = append(options, libpod.WithCgroupParent(c.CgroupParent))
}
- if c.Cgroups == "disabled" {
- options = append(options, libpod.WithNoCgroups())
+ if c.Cgroups != "" {
+ options = append(options, libpod.WithCgroupsMode(c.Cgroups))
}
return options, nil
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index 7a220012f..cae055bb0 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -358,10 +358,10 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
return nil, errors.New("cannot specify resource limits when cgroups are disabled is specified")
}
configSpec.Linux.Resources = &spec.LinuxResources{}
- case "enabled", "":
+ case "enabled", "no-conmon", "":
// Do nothing
default:
- return nil, errors.New("unrecognized option for cgroups; supported are 'default' and 'disabled'")
+ return nil, errors.New("unrecognized option for cgroups; supported are 'default', 'disabled', 'no-conmon'")
}
// Add annotations
diff --git a/pkg/systemdgen/systemdgen.go b/pkg/systemdgen/systemdgen.go
index 745b708e4..26b3b3756 100644
--- a/pkg/systemdgen/systemdgen.go
+++ b/pkg/systemdgen/systemdgen.go
@@ -153,13 +153,14 @@ func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, erro
if len(info.CreateCommand) < index+1 {
return "", errors.Errorf("container's create command is too short or invalid: %v", info.CreateCommand)
}
- // We're hard-coding the first four arguments and append the
- // CreatCommand with a stripped command and subcomand.
+ // We're hard-coding the first five arguments and append the
+ // CreateCommand with a stripped command and subcomand.
command := []string{
info.Executable,
"run",
"--conmon-pidfile", "/%t/%n-pid",
"--cidfile", "/%t/%n-cid",
+ "--cgroups=no-conmon",
}
command = append(command, info.CreateCommand[index:]...)
info.RunCommand = strings.Join(command, " ")
diff --git a/pkg/systemdgen/systemdgen_test.go b/pkg/systemdgen/systemdgen_test.go
index 9c6933d17..ee2429407 100644
--- a/pkg/systemdgen/systemdgen_test.go
+++ b/pkg/systemdgen/systemdgen_test.go
@@ -122,7 +122,7 @@ Documentation=man:podman-generate-systemd(1)
[Service]
Restart=always
ExecStartPre=/usr/bin/rm -f /%t/%n-pid /%t/%n-cid
-ExecStart=/usr/bin/podman run --conmon-pidfile /%t/%n-pid --cidfile /%t/%n-cid --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
+ExecStart=/usr/bin/podman run --conmon-pidfile /%t/%n-pid --cidfile /%t/%n-cid --cgroups=no-conmon --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
ExecStop=/usr/bin/podman stop --ignore --cidfile /%t/%n-cid -t 42
ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile /%t/%n-cid
PIDFile=/%t/%n-pid