diff --git a/.gitignore b/.gitignore
index f1980a2..352fdba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,36 +1,5 @@
-examples/attach
-examples/attach_with_pipes
-examples/checkpoint
-examples/clone
-examples/concurrent_create
-examples/concurrent_destroy
-examples/concurrent_shutdown
-examples/concurrent_start
-examples/concurrent_stop
-examples/concurrent_stress
-examples/config
-examples/console
-examples/create
-examples/create_snapshot
-examples/destroy
-examples/destroy_snapshots
-examples/device_add_remove
-examples/execute
-examples/freeze
-examples/interfaces
-examples/ipaddress
-examples/limit
-examples/list
-examples/list_keys
-examples/list_snapshots
-examples/reboot
-examples/rename
-examples/restore_snapshot
-examples/shutdown
-examples/start
-examples/stats
-examples/stop
-examples/unfreeze
+examples/*/*
+!examples/*/*.go
 coverage.out
 tags
 *.swp
diff --git a/.travis.yml b/.travis.yml
index 5e054c0..a67deb8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,10 +4,9 @@ os:
   - linux
 
 go:
-  - 1.6
-  - 1.7
-  - 1.8
-  - 1.9
+  - "1.10"
+  - "1.11"
+  - "1.12"
   - tip
 
 matrix:
@@ -18,29 +17,31 @@ matrix:
 before_install:
  - sudo add-apt-repository ppa:ubuntu-lxc/daily -y
  - sudo apt-get update
- - sudo apt-get install -qq lxc lxc-dev uidmap
+ - sudo apt-get install -qq lxc lxc-dev uidmap busybox
  - echo "${USER}:100000:65536" | sudo tee /etc/subuid
  - echo "${USER}:100000:65536" | sudo tee /etc/subgid
  - echo "${USER} veth lxcbr0 10" | sudo tee -a /etc/lxc/lxc-usernet
- - mkdir -p ~/.config/lxc/
- - cp /etc/lxc/default.conf ~/.config/lxc/default.conf
- - echo "lxc.idmap = u 0 100000 65536" | sudo tee -a ~/.config/lxc/default.conf
- - echo "lxc.idmap = g 0 100000 65536" | sudo tee -a ~/.config/lxc/default.conf
+ - mkdir -p ${HOME}/.config/lxc/
+ - cp /etc/lxc/default.conf ${HOME}/.config/lxc/default.conf
+ - echo "lxc.id_map = u 0 100000 65536" | sudo tee -a ${HOME}/.config/lxc/default.conf
+ - echo "lxc.id_map = g 0 100000 65536" | sudo tee -a ${HOME}/.config/lxc/default.conf
  - "make setup-test-cgroup"
- - mkdir -p ~/.local/share
- - chmod +x ~/.local/share
- - chmod +x ~/.local/
+ - mkdir -p ${HOME}/.local/share/lxc
  - chmod +x ${HOME}
+ - chmod +x ${HOME}/.local
+ - chmod +x ${HOME}/.local/share
+ - chmod +x ${HOME}/.local/share/lxc
 
 install:
+  - go get golang.org/x/tools/cmd/goimports
   - go get gopkg.in/lxc/go-lxc.v2
 
 script:
   - "make all"
   - "make test"
   - "make test-race"
-  - "make test-unprivileged"
-  - "make test-unprivileged-race"
+  - "make test-privileged"
+  - "make test-privileged-race"
   - "make cover"
 
 notifications:
diff --git a/Makefile b/Makefile
index 149ce66..8e655e2 100644
--- a/Makefile
+++ b/Makefile
@@ -8,25 +8,31 @@ format:
 	@gofmt -s -w *.go
 	@goimports -w *.go || true
 
-test:
-	@echo "$(OK_COLOR)==> Running go test $(NO_COLOR)"
-	@sudo `which go` test -v
+test-privileged:
+	@echo "$(OK_COLOR)==> Running tests for privileged user $(NO_COLOR)"
+	@sudo `which go` test -v -coverprofile=/tmp/priv.out
+	@sudo `which go` test -tags static_build -v -coverprofile=/tmp/priv.out
 
-test-race:
-	@echo "$(OK_COLOR)==> Running go test $(NO_COLOR)"
+test-privileged-race:
+	@echo "$(OK_COLOR)==> Running tests with -race flag for privileged user $(NO_COLOR)"
 	@sudo `which go` test -race -v
+	@sudo `which go` test -tags static_build -race -v
 
-test-unprivileged:
-	@echo "$(OK_COLOR)==> Running go test for unprivileged user$(NO_COLOR)"
-	@`which go` test -v
+test:
+	@echo "$(OK_COLOR)==> Running tests for unprivileged user $(NO_COLOR)"
+	@`which go` test -v -coverprofile=/tmp/unpriv.out
+	@`which go` test -tags static_build -v -coverprofile=/tmp/unpriv.out
 
-test-unprivileged-race:
-	@echo "$(OK_COLOR)==> Running go test for unprivileged user$(NO_COLOR)"
+test-race:
+	@echo "$(OK_COLOR)==> Running tests with -race flag for unprivileged user $(NO_COLOR)"
 	@`which go` test -race -v
+	@`which go` test -tags static_build -race -v
 
 cover:
-	@sudo `which go` test -v -coverprofile=coverage.out
-	@`which go` tool cover -func=coverage.out
+	@echo "$(OK_COLOR)==> Running cover for privileged user $(NO_COLOR)"
+	@`which go` tool cover -func=/tmp/priv.out || true
+	@echo "$(OK_COLOR)==> Running cover for unprivileged user $(NO_COLOR)"
+	@`which go` tool cover -func=/tmp/unpriv.out || true
 
 doc:
 	@`which godoc` gopkg.in/lxc/go-lxc.v2 | less
@@ -40,7 +46,7 @@ lint:
 	@`which golint` . || true
 
 escape-analysis:
-	@go build -gcflags -m
+	@`which go` build -gcflags -m
 
 ctags:
 	@ctags -R --languages=c,go
diff --git a/README.md b/README.md
index d737fa7..13cad24 100644
--- a/README.md
+++ b/README.md
@@ -1,40 +1,119 @@
+[![go-lxc](https://linuxcontainers.org/static/img/containers.png)](https://linuxcontainers.org/)
 # Go Bindings for LXC (Linux Containers)
 
-This package implements [Go](http://golang.org) bindings for the [LXC](http://linuxcontainers.org/) C API (liblxc).
+LXC is the well-known and heavily tested low-level Linux container runtime. It
+is in active development since 2008 and has proven itself in critical
+production environments world-wide. Some of its core contributors are the same
+people that helped to implement various well-known containerization features
+inside the Linux kernel.
+
+
+This package implements [Go](https://golang.org) bindings for the [LXC](https://linuxcontainers.org/lxc/introduction/) C API (liblxc).
+
+## Status
+Type            | Service               | Status
+---             | ---                   | ---
+CI (Linux)      | Travis                | [![Build Status](https://travis-ci.org/lxc/go-lxc.svg?branch=v2)](https://travis-ci.org/lxc/go-lxc/)
+Go documentation    | Godoc                 | [![GoDoc](https://godoc.org/gopkg.in/lxc/go-lxc.v2?status.svg)](https://godoc.org/gopkg.in/lxc/go-lxc.v2)
+Static analysis     | GoReport              | [![Go Report Card](https://goreportcard.com/badge/gopkg.in/lxc/go-lxc.v2)](https://goreportcard.com/report/gopkg.in/lxc/go-lxc.v2)
 
 ## Requirements
 
-This package requires [LXC 1.x](https://github.com/lxc/lxc/releases) and its development package to be installed. Works with [Go 1.x](http://golang.org/dl). Following command should install required dependencies on Ubuntu:
+This package requires [LXC >= 1.0.0](https://github.com/lxc/lxc/releases) and its development package and their dependencies to be installed. Additionally, go-lxc requires Golang 1.10 or later to work. Following command should install required dependencies on Ubuntu 18.10:
 
-	apt-get install -y pkg-config lxc-dev
+```bash
+sudo apt update
+sudo apt install git golang gcc make liblxc1 liblxc-dev lxc-utils pkg-config
+```
 
 ## Installing
 
 To install it, run:
 
-    go get gopkg.in/lxc/go-lxc.v2
+```bash
+go get gopkg.in/lxc/go-lxc.v2
+```
+
+## Trying
+
+To try examples, run:
+
+```bash
+# cd ~/go/src/gopkg.in/lxc/go-lxc.v2/examples/
 
-## Documentation
+# make
+==> Running go vet 
+==> Building ...
+...
 
-Documentation can be found at [GoDoc](http://godoc.org/gopkg.in/lxc/go-lxc.v2).
+# create/create
+2018/12/27 22:39:27 Creating container...
+
+# start/start 
+2018/12/27 22:39:39 Starting the container...
+2018/12/27 22:39:39 Waiting container to startup networking...
+
+# attach/attach 
+2018/12/27 22:39:46 AttachShell
+root@rubik:/# hostname
+rubik
+root@rubik:/# exit
+exit
+2018/12/27 22:39:52 RunCommand
+uid=0(root) gid=0(root) groups=0(root)
+
+# stop/stop 
+2018/12/27 22:39:54 Stopping the container...
+
+# destroy/destroy 
+2018/12/27 22:39:57 Destroying container...
+```
 
 ## Stability
 
 The package API will remain stable as described in [gopkg.in](https://gopkg.in).
 
+## Backwards Compatibility
+
+LXC has always focused on strong backwards compatibility. In fact, the API hasn't been broken from release `1.0.0` onwards. Main LXC is currently at version `2.*.*`.
+
 ## Examples
 
 See the [examples](https://github.com/lxc/go-lxc/tree/v2/examples) directory for some.
 
+## Bug reports
+
+Bug reports can be filed at: <https://github.com/lxc/go-lxc/issues/new>
+
 ## Contributing
 
-We'd love to see go-lxc improve. To contribute to go-lxc;
+Fixes and new features are greatly appreciated. We'd love to see go-lxc improve. To contribute to go-lxc;
 
 * **Fork** the repository
 * **Modify** your fork
 * Ensure your fork **passes all tests**
 * **Send** a pull request
 	* Bonus points if the pull request includes *what* you changed, *why* you changed it, and *tests* attached.
-	* For the love of all that is holy, please use `go fmt` *before* you send the pull request.
 
-We'll review it and merge it in if it's appropriate.
+## Getting help
+
+When you find you need help, the LXC projects provides you with several options.
+
+### Discuss Forum
+
+We maintain an discuss forum at
+
+- https://discuss.linuxcontainers.org/
+
+where you can get support.
+
+### IRC
+
+You can find support by joining `#lxcontainers` on `Freenode`.
+
+### Mailing Lists
+
+You can check out one of the two LXC mailing list archives and register if interested:
+
+- http://lists.linuxcontainers.org/listinfo/lxc-devel
+- http://lists.linuxcontainers.org/listinfo/lxc-users
\ No newline at end of file
diff --git a/container.go b/container.go
index 58f1d7f..5cada46 100644
--- a/container.go
+++ b/container.go
@@ -101,6 +101,18 @@ func (c *Container) setCgroupItemWithByteSize(filename string, limit ByteSize, m
 	return nil
 }
 
+// Release decrements the reference counter of the container object.
+// nil on success or if reference was successfully dropped and container has been freed, and ErrReleaseFailed on error.
+func (c *Container) Release() error {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+
+	if C.lxc_container_put(c.container) == -1 {
+		return ErrReleaseFailed
+	}
+	return nil
+}
+
 func (c *Container) name() string {
 	return C.GoString(c.container.name)
 }
@@ -113,7 +125,7 @@ func (c *Container) Name() string {
 	return c.name()
 }
 
-// String returns the string represantation of container.
+// String returns the string representation of container.
 func (c *Container) String() string {
 	c.mu.RLock()
 	defer c.mu.RUnlock()
@@ -840,21 +852,24 @@ func (c *Container) ConfigKeys(key ...string) []string {
 	c.mu.RLock()
 	defer c.mu.RUnlock()
 
-	var keys *_Ctype_char
-
+	var ret string
 	if key != nil && len(key) == 1 {
 		ckey := C.CString(key[0])
 		defer C.free(unsafe.Pointer(ckey))
 
 		// allocated in lxc.c
-		keys = C.go_lxc_get_keys(c.container, ckey)
+		keys := C.go_lxc_get_keys(c.container, ckey)
 		defer C.free(unsafe.Pointer(keys))
+
+		ret = strings.TrimSpace(C.GoString(keys))
 	} else {
 		// allocated in lxc.c
-		keys = C.go_lxc_get_keys(c.container, nil)
+		keys := C.go_lxc_get_keys(c.container, nil)
 		defer C.free(unsafe.Pointer(keys))
+
+		ret = strings.TrimSpace(C.GoString(keys))
 	}
-	ret := strings.TrimSpace(C.GoString(keys))
+
 	return strings.Split(ret, "\n")
 }
 
@@ -1803,7 +1818,7 @@ func (c *Container) Migrate(cmd uint, opts MigrateOptions) error {
 	return nil
 }
 
-// AttachInterface attaches specifed netdev to the container.
+// AttachInterface attaches specified netdev to the container.
 func (c *Container) AttachInterface(source, destination string) error {
 	c.mu.Lock()
 	defer c.mu.Unlock()
@@ -1824,7 +1839,7 @@ func (c *Container) AttachInterface(source, destination string) error {
 	return nil
 }
 
-// DetachInterface detaches specifed netdev from the container.
+// DetachInterface detaches specified netdev from the container.
 func (c *Container) DetachInterface(source string) error {
 	c.mu.Lock()
 	defer c.mu.Unlock()
@@ -1842,7 +1857,7 @@ func (c *Container) DetachInterface(source string) error {
 	return nil
 }
 
-// DetachInterfaceRename detaches specifed netdev from the container and renames it.
+// DetachInterfaceRename detaches specified netdev from the container and renames it.
 func (c *Container) DetachInterfaceRename(source, target string) error {
 	c.mu.Lock()
 	defer c.mu.Unlock()
diff --git a/debian/changelog b/debian/changelog
index 26e7a02..a25cf57 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang-gopkg-lxc-go-lxc.v2 (0.0~git20190606.338b579-1) UNRELEASED; urgency=medium
+
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Sun, 23 Jun 2019 06:21:03 +0000
+
 golang-gopkg-lxc-go-lxc.v2 (0.0~git20181101.0aadfc3-1) unstable; urgency=medium
 
   [ Alexandre Viau ]
diff --git a/error.go b/error.go
index b89d903..533cb10 100644
--- a/error.go
+++ b/error.go
@@ -6,81 +6,72 @@
 
 package lxc
 
-var (
-	ErrAddDeviceNodeFailed           = NewError("adding device to container failed")
-	ErrAllocationFailed              = NewError("allocating memory failed")
-	ErrAlreadyDefined                = NewError("container already defined")
-	ErrAlreadyFrozen                 = NewError("container is already frozen")
-	ErrAlreadyRunning                = NewError("container is already running")
-	ErrAttachFailed                  = NewError("attaching to the container failed")
-	ErrAttachInterfaceFailed         = NewError("attaching specified netdev to the container failed")
-	ErrBlkioUsage                    = NewError("BlkioUsage for the container failed")
-	ErrCheckpointFailed              = NewError("checkpoint failed")
-	ErrClearingConfigItemFailed      = NewError("clearing config item for the container failed")
-	ErrClearingCgroupItemFailed      = NewError("clearing cgroup item for the container failed")
-	ErrCloneFailed                   = NewError("cloning the container failed")
-	ErrCloseAllFdsFailed             = NewError("setting close_all_fds flag for container failed")
-	ErrCreateFailed                  = NewError("creating the container failed")
-	ErrCreateSnapshotFailed          = NewError("snapshotting the container failed")
-	ErrDaemonizeFailed               = NewError("setting daemonize flag for container failed")
-	ErrDestroyAllSnapshotsFailed     = NewError("destroying all snapshots failed")
-	ErrDestroyFailed                 = NewError("destroying the container failed")
-	ErrDestroySnapshotFailed         = NewError("destroying the snapshot failed")
-	ErrDestroyWithAllSnapshotsFailed = NewError("destroying the container with all snapshots failed")
-	ErrDetachInterfaceFailed         = NewError("detaching specified netdev to the container failed")
-	ErrExecuteFailed                 = NewError("executing the command in a temporary container failed")
-	ErrFreezeFailed                  = NewError("freezing the container failed")
-	ErrInsufficientNumberOfArguments = NewError("insufficient number of arguments were supplied")
-	ErrInterfaces                    = NewError("getting interface names for the container failed")
-	ErrIPAddresses                   = NewError("getting IP addresses of the container failed")
-	ErrIPAddress                     = NewError("getting IP address on the interface of the container failed")
-	ErrIPv4Addresses                 = NewError("getting IPv4 addresses of the container failed")
-	ErrIPv6Addresses                 = NewError("getting IPv6 addresses of the container failed")
-	ErrKMemLimit                     = NewError("your kernel does not support cgroup kernel memory controller")
-	ErrLoadConfigFailed              = NewError("loading config file for the container failed")
-	ErrMemLimit                      = NewError("your kernel does not support cgroup memory controller")
-	ErrMemorySwapLimit               = NewError("your kernel does not support cgroup swap controller")
-	ErrMethodNotAllowed              = NewError("the requested method is not currently supported with unprivileged containers")
-	ErrNewFailed                     = NewError("allocating the container failed")
-	ErrNoSnapshot                    = NewError("container has no snapshot")
-	ErrNotDefined                    = NewError("container is not defined")
-	ErrNotFrozen                     = NewError("container is not frozen")
-	ErrNotRunning                    = NewError("container is not running")
-	ErrNotSupported                  = NewError("method is not supported by this LXC version")
-	ErrRebootFailed                  = NewError("rebooting the container failed")
-	ErrRemoveDeviceNodeFailed        = NewError("removing device from container failed")
-	ErrRenameFailed                  = NewError("renaming the container failed")
-	ErrRestoreFailed                 = NewError("restore failed")
-	ErrRestoreSnapshotFailed         = NewError("restoring the container failed")
-	ErrSaveConfigFailed              = NewError("saving config file for the container failed")
-	ErrSettingCgroupItemFailed       = NewError("setting cgroup item for the container failed")
-	ErrSettingConfigItemFailed       = NewError("setting config item for the container failed")
-	ErrSettingConfigPathFailed       = NewError("setting config file for the container failed")
-	ErrSettingKMemoryLimitFailed     = NewError("setting kernel memory limit for the container failed")
-	ErrSettingMemoryLimitFailed      = NewError("setting memory limit for the container failed")
-	ErrSettingMemorySwapLimitFailed  = NewError("setting memory+swap limit for the container failed")
-	ErrSettingSoftMemoryLimitFailed  = NewError("setting soft memory limit for the container failed")
-	ErrShutdownFailed                = NewError("shutting down the container failed")
-	ErrSoftMemLimit                  = NewError("your kernel does not support cgroup memory controller")
-	ErrStartFailed                   = NewError("starting the container failed")
-	ErrStopFailed                    = NewError("stopping the container failed")
-	ErrTemplateNotAllowed            = NewError("unprivileged users only allowed to use \"download\" template")
-	ErrUnfreezeFailed                = NewError("unfreezing the container failed")
-	ErrUnknownBackendStore           = NewError("unknown backend type")
+const (
+	ErrAddDeviceNodeFailed           = lxcError("adding device to container failed")
+	ErrAllocationFailed              = lxcError("allocating memory failed")
+	ErrAlreadyDefined                = lxcError("container already defined")
+	ErrAlreadyFrozen                 = lxcError("container is already frozen")
+	ErrAlreadyRunning                = lxcError("container is already running")
+	ErrAttachFailed                  = lxcError("attaching to the container failed")
+	ErrAttachInterfaceFailed         = lxcError("attaching specified netdev to the container failed")
+	ErrBlkioUsage                    = lxcError("BlkioUsage for the container failed")
+	ErrCheckpointFailed              = lxcError("checkpoint failed")
+	ErrClearingConfigItemFailed      = lxcError("clearing config item for the container failed")
+	ErrClearingCgroupItemFailed      = lxcError("clearing cgroup item for the container failed")
+	ErrCloneFailed                   = lxcError("cloning the container failed")
+	ErrCloseAllFdsFailed             = lxcError("setting close_all_fds flag for container failed")
+	ErrCreateFailed                  = lxcError("creating the container failed")
+	ErrCreateSnapshotFailed          = lxcError("snapshotting the container failed")
+	ErrDaemonizeFailed               = lxcError("setting daemonize flag for container failed")
+	ErrDestroyAllSnapshotsFailed     = lxcError("destroying all snapshots failed")
+	ErrDestroyFailed                 = lxcError("destroying the container failed")
+	ErrDestroySnapshotFailed         = lxcError("destroying the snapshot failed")
+	ErrDestroyWithAllSnapshotsFailed = lxcError("destroying the container with all snapshots failed")
+	ErrDetachInterfaceFailed         = lxcError("detaching specified netdev to the container failed")
+	ErrExecuteFailed                 = lxcError("executing the command in a temporary container failed")
+	ErrFreezeFailed                  = lxcError("freezing the container failed")
+	ErrInsufficientNumberOfArguments = lxcError("insufficient number of arguments were supplied")
+	ErrInterfaces                    = lxcError("getting interface names for the container failed")
+	ErrIPAddresses                   = lxcError("getting IP addresses of the container failed")
+	ErrIPAddress                     = lxcError("getting IP address on the interface of the container failed")
+	ErrIPv4Addresses                 = lxcError("getting IPv4 addresses of the container failed")
+	ErrIPv6Addresses                 = lxcError("getting IPv6 addresses of the container failed")
+	ErrKMemLimit                     = lxcError("your kernel does not support cgroup kernel memory controller")
+	ErrLoadConfigFailed              = lxcError("loading config file for the container failed")
+	ErrMemLimit                      = lxcError("your kernel does not support cgroup memory controller")
+	ErrMemorySwapLimit               = lxcError("your kernel does not support cgroup swap controller")
+	ErrMethodNotAllowed              = lxcError("the requested method is not currently supported with unprivileged containers")
+	ErrNewFailed                     = lxcError("allocating the container failed")
+	ErrNoSnapshot                    = lxcError("container has no snapshot")
+	ErrNotDefined                    = lxcError("container is not defined")
+	ErrNotFrozen                     = lxcError("container is not frozen")
+	ErrNotRunning                    = lxcError("container is not running")
+	ErrNotSupported                  = lxcError("method is not supported by this LXC version")
+	ErrRebootFailed                  = lxcError("rebooting the container failed")
+	ErrRemoveDeviceNodeFailed        = lxcError("removing device from container failed")
+	ErrRenameFailed                  = lxcError("renaming the container failed")
+	ErrRestoreFailed                 = lxcError("restore failed")
+	ErrRestoreSnapshotFailed         = lxcError("restoring the container failed")
+	ErrSaveConfigFailed              = lxcError("saving config file for the container failed")
+	ErrSettingCgroupItemFailed       = lxcError("setting cgroup item for the container failed")
+	ErrSettingConfigItemFailed       = lxcError("setting config item for the container failed")
+	ErrSettingConfigPathFailed       = lxcError("setting config file for the container failed")
+	ErrSettingKMemoryLimitFailed     = lxcError("setting kernel memory limit for the container failed")
+	ErrSettingMemoryLimitFailed      = lxcError("setting memory limit for the container failed")
+	ErrSettingMemorySwapLimitFailed  = lxcError("setting memory+swap limit for the container failed")
+	ErrSettingSoftMemoryLimitFailed  = lxcError("setting soft memory limit for the container failed")
+	ErrShutdownFailed                = lxcError("shutting down the container failed")
+	ErrSoftMemLimit                  = lxcError("your kernel does not support cgroup memory controller")
+	ErrStartFailed                   = lxcError("starting the container failed")
+	ErrStopFailed                    = lxcError("stopping the container failed")
+	ErrTemplateNotAllowed            = lxcError("unprivileged users only allowed to use \"download\" template")
+	ErrUnfreezeFailed                = lxcError("unfreezing the container failed")
+	ErrUnknownBackendStore           = lxcError("unknown backend type")
+	ErrReleaseFailed                 = lxcError("releasing the container failed")
 )
 
-// Error represents a basic error that implies the error interface.
-type Error struct {
-	Message string
-}
-
-// NewError creates a new error with the given msg argument.
-func NewError(msg string) error {
-	return &Error{
-		Message: msg,
-	}
-}
+type lxcError string
 
-func (e *Error) Error() string {
-	return e.Message
+func (e lxcError) Error() string {
+	return string(e)
 }
diff --git a/examples/Makefile b/examples/Makefile
index effce0c..09121ab 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,33 +1,33 @@
 NO_COLOR=\033[0m
 OK_COLOR=\033[0;32m
 
-ALL_GO_FILES = $(wildcard *.go)
-ALL_FILES = $(patsubst %.go,%,$(ALL_GO_FILES))
+ALL_GO_FILES = $(wildcard */*.go)
+ALL_BIN_FILES = $(patsubst %.go,%,$(ALL_GO_FILES))
 
-all: $(ALL_FILES)
+all: $(ALL_GO_FILES)
 
 define PROGRAM_template
-$(1): format vet lint
+$(1): vet
 	@echo "$(OK_COLOR)==> Building $(1) $(NO_COLOR)"
-	@go build $(1).go
+	@cd $(dir $1); go build
 endef
 
-$(foreach prog,$(ALL_FILES),$(eval $(call PROGRAM_template,$(prog))))
+$(foreach prog,$(ALL_GO_FILES),$(eval $(call PROGRAM_template,$(prog))))
 
 clean:
-	@$(foreach file,$(ALL_FILES),rm -f $(file);)
+	@$(foreach file,$(ALL_BIN_FILES),rm -f $(file);)
 
 format:
 	@echo "$(OK_COLOR)==> Formatting the code $(NO_COLOR)"
-	@gofmt -s -w *.go
-	@goimports -w *.go
+	@$(foreach file,$(ALL_GO_FILES),gofmt -s -w $(file);)
+	@$(foreach file,$(ALL_GO_FILES),goimports -w $(file);)
 
 vet:
 	@echo "$(OK_COLOR)==> Running go vet $(NO_COLOR)"
-	@`which go` vet .
+	@$(foreach file,$(ALL_GO_FILES),go vet -all $(file);)
 
 lint:
 	@echo "$(OK_COLOR)==> Running golint $(NO_COLOR)"
-	@`which golint` .
+	@$(foreach file,$(ALL_GO_FILES),golint $(file);)
 
 .PHONY: all clean format vet lint
diff --git a/examples/attach.go b/examples/attach/attach.go
similarity index 98%
rename from examples/attach.go
rename to examples/attach/attach.go
index b8b4b48..528936c 100644
--- a/examples/attach.go
+++ b/examples/attach/attach.go
@@ -35,6 +35,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	options := lxc.DefaultAttachOptions
 	options.ClearEnv = false
diff --git a/examples/attach_with_pipes.go b/examples/attach_with_pipes/attach_with_pipes.go
similarity index 99%
rename from examples/attach_with_pipes.go
rename to examples/attach_with_pipes/attach_with_pipes.go
index ece8aaa..e1c6156 100644
--- a/examples/attach_with_pipes.go
+++ b/examples/attach_with_pipes/attach_with_pipes.go
@@ -39,6 +39,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	stdoutReader, stdoutWriter, err := os.Pipe()
 	if err != nil {
diff --git a/examples/checkpoint.go b/examples/checkpoint/checkpoint.go
similarity index 98%
rename from examples/checkpoint.go
rename to examples/checkpoint/checkpoint.go
index a3a5a85..6a1fee8 100644
--- a/examples/checkpoint.go
+++ b/examples/checkpoint/checkpoint.go
@@ -35,6 +35,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	if verbose {
 		c.SetVerbosity(lxc.Verbose)
diff --git a/examples/clone.go b/examples/clone/clone.go
similarity index 98%
rename from examples/clone.go
rename to examples/clone/clone.go
index bc95b7c..1be4f3b 100644
--- a/examples/clone.go
+++ b/examples/clone/clone.go
@@ -31,6 +31,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	if backend == 0 {
 		log.Fatalf("ERROR: %s\n", lxc.ErrUnknownBackendStore)
diff --git a/examples/concurrent_create.go b/examples/concurrent_create/concurrent_create.go
similarity index 97%
rename from examples/concurrent_create.go
rename to examples/concurrent_create/concurrent_create.go
index 5dafc62..8ac5897 100644
--- a/examples/concurrent_create.go
+++ b/examples/concurrent_create/concurrent_create.go
@@ -39,6 +39,7 @@ func main() {
 			if err != nil {
 				log.Fatalf("ERROR: %s\n", err.Error())
 			}
+			defer c.Release()
 
 			log.Printf("Creating the container (%d)...\n", i)
 			if err := c.Create(options); err != nil {
diff --git a/examples/concurrent_destroy.go b/examples/concurrent_destroy/concurrent_destroy.go
similarity index 97%
rename from examples/concurrent_destroy.go
rename to examples/concurrent_destroy/concurrent_destroy.go
index 7ea678d..04e06af 100644
--- a/examples/concurrent_destroy.go
+++ b/examples/concurrent_destroy/concurrent_destroy.go
@@ -38,6 +38,7 @@ func main() {
 			if err != nil {
 				log.Fatalf("ERROR: %s\n", err.Error())
 			}
+			defer c.Release()
 
 			log.Printf("Destroying the container (%d)...\n", i)
 			if err := c.Destroy(); err != nil {
diff --git a/examples/concurrent_shutdown.go b/examples/concurrent_shutdown/concurrent_shutdown.go
similarity index 97%
rename from examples/concurrent_shutdown.go
rename to examples/concurrent_shutdown/concurrent_shutdown.go
index adcdadf..a795f2f 100644
--- a/examples/concurrent_shutdown.go
+++ b/examples/concurrent_shutdown/concurrent_shutdown.go
@@ -39,6 +39,7 @@ func main() {
 			if err != nil {
 				log.Fatalf("ERROR: %s\n", err.Error())
 			}
+			defer c.Release()
 
 			log.Printf("Shutting down the container (%d)...\n", i)
 			if err := c.Shutdown(30 * time.Second); err != nil {
diff --git a/examples/concurrent_start.go b/examples/concurrent_start/concurrent_start.go
similarity index 97%
rename from examples/concurrent_start.go
rename to examples/concurrent_start/concurrent_start.go
index 3d01656..6cfc7af 100644
--- a/examples/concurrent_start.go
+++ b/examples/concurrent_start/concurrent_start.go
@@ -38,6 +38,7 @@ func main() {
 			if err != nil {
 				log.Fatalf("ERROR: %s\n", err.Error())
 			}
+			defer c.Release()
 
 			log.Printf("Starting the container (%d)...\n", i)
 			if err := c.Start(); err != nil {
diff --git a/examples/concurrent_stop.go b/examples/concurrent_stop/concurrent_stop.go
similarity index 97%
rename from examples/concurrent_stop.go
rename to examples/concurrent_stop/concurrent_stop.go
index 57fc2c1..d5f506a 100644
--- a/examples/concurrent_stop.go
+++ b/examples/concurrent_stop/concurrent_stop.go
@@ -38,6 +38,7 @@ func main() {
 			if err != nil {
 				log.Fatalf("ERROR: %s\n", err.Error())
 			}
+			defer c.Release()
 
 			log.Printf("Stoping the container (%d)...\n", i)
 			if err := c.Stop(); err != nil {
diff --git a/examples/concurrent_stress.go b/examples/concurrent_stress/concurrent_stress.go
similarity index 99%
rename from examples/concurrent_stress.go
rename to examples/concurrent_stress/concurrent_stress.go
index f9026a9..b68deaa 100644
--- a/examples/concurrent_stress.go
+++ b/examples/concurrent_stress/concurrent_stress.go
@@ -62,6 +62,7 @@ func main() {
 					if err != nil {
 						log.Fatalf("ERROR: %s\n", err.Error())
 					}
+					defer c.Release()
 
 					if mode == "CREATE" && startstop == false {
 						log.Printf("\t\tCreating the container (%d)...\n", i)
diff --git a/examples/config.go b/examples/config/config.go
similarity index 98%
rename from examples/config.go
rename to examples/config/config.go
index 439539c..b5a8fbd 100644
--- a/examples/config.go
+++ b/examples/config/config.go
@@ -27,11 +27,11 @@ func init() {
 }
 
 func main() {
-
 	c, err := lxc.NewContainer(name, lxcpath)
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	//setting hostname
 	err = c.SetConfigItem("lxc.utsname", hostname)
diff --git a/examples/console.go b/examples/console/console.go
similarity index 97%
rename from examples/console.go
rename to examples/console/console.go
index 651f9ff..b26efa1 100644
--- a/examples/console.go
+++ b/examples/console/console.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Attaching to container's console...\n")
 	if err := c.Console(lxc.DefaultConsoleOptions); err != nil {
diff --git a/examples/create.go b/examples/create/create.go
similarity index 98%
rename from examples/create.go
rename to examples/create/create.go
index 1714bb3..1e71d25 100644
--- a/examples/create.go
+++ b/examples/create/create.go
@@ -43,6 +43,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Creating container...\n")
 	if verbose {
diff --git a/examples/create_snapshot.go b/examples/create_snapshot/create_snapshot.go
similarity index 97%
rename from examples/create_snapshot.go
rename to examples/create_snapshot/create_snapshot.go
index d86cd1b..b31d2fa 100644
--- a/examples/create_snapshot.go
+++ b/examples/create_snapshot/create_snapshot.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Snapshoting the container...\n")
 	if _, err := c.CreateSnapshot(); err != nil {
diff --git a/examples/destroy.go b/examples/destroy/destroy.go
similarity index 97%
rename from examples/destroy.go
rename to examples/destroy/destroy.go
index c294385..81767dc 100644
--- a/examples/destroy.go
+++ b/examples/destroy/destroy.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Destroying container...\n")
 	if err := c.Destroy(); err != nil {
diff --git a/examples/destroy_snapshots.go b/examples/destroy_snapshots/destroy_snapshots.go
similarity index 97%
rename from examples/destroy_snapshots.go
rename to examples/destroy_snapshots/destroy_snapshots.go
index 07d1b14..5210f3e 100644
--- a/examples/destroy_snapshots.go
+++ b/examples/destroy_snapshots/destroy_snapshots.go
@@ -27,5 +27,6 @@ func main() {
 				log.Fatalf("ERROR: %s\n", err.Error())
 			}
 		}
+		c[i].Release()
 	}
 }
diff --git a/examples/device_add_remove.go b/examples/device_add_remove/device_add_remove.go
similarity index 97%
rename from examples/device_add_remove.go
rename to examples/device_add_remove/device_add_remove.go
index 56b9c83..da6783f 100644
--- a/examples/device_add_remove.go
+++ b/examples/device_add_remove/device_add_remove.go
@@ -30,6 +30,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	if err := c.AddDeviceNode("/dev/network_latency"); err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
diff --git a/examples/execute.go b/examples/execute/execute.go
similarity index 97%
rename from examples/execute.go
rename to examples/execute/execute.go
index a5cb350..fc5af47 100644
--- a/examples/execute.go
+++ b/examples/execute/execute.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	c.LoadConfigFile(lxc.DefaultConfigPath())
 	if output, err := c.Execute("uname", "-a"); err != nil {
diff --git a/examples/freeze.go b/examples/freeze/freeze.go
similarity index 97%
rename from examples/freeze.go
rename to examples/freeze/freeze.go
index c13a123..7f063c5 100644
--- a/examples/freeze.go
+++ b/examples/freeze/freeze.go
@@ -30,6 +30,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Freezing the container...\n")
 	if err := c.Freeze(); err != nil {
diff --git a/examples/interfaces.go b/examples/interfaces/interfaces.go
similarity index 97%
rename from examples/interfaces.go
rename to examples/interfaces/interfaces.go
index eea8580..c61beff 100644
--- a/examples/interfaces.go
+++ b/examples/interfaces/interfaces.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Interfaces\n")
 	if interfaces, err := c.Interfaces(); err != nil {
diff --git a/examples/ipaddress.go b/examples/ipaddress/ipaddress.go
similarity index 98%
rename from examples/ipaddress.go
rename to examples/ipaddress/ipaddress.go
index f52fd77..e4a878b 100644
--- a/examples/ipaddress.go
+++ b/examples/ipaddress/ipaddress.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("IPAddress(\"lo\")\n")
 	if addresses, err := c.IPAddress("lo"); err != nil {
diff --git a/examples/limit.go b/examples/limit/limit.go
similarity index 98%
rename from examples/limit.go
rename to examples/limit/limit.go
index 2d2a38b..dd5c453 100644
--- a/examples/limit.go
+++ b/examples/limit/limit.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	memLimit, err := c.MemoryLimit()
 	if err != nil {
diff --git a/examples/list.go b/examples/list/list.go
similarity index 94%
rename from examples/list.go
rename to examples/list/list.go
index 8434225..0f17030 100644
--- a/examples/list.go
+++ b/examples/list/list.go
@@ -27,6 +27,7 @@ func main() {
 	c := lxc.DefinedContainers(lxcpath)
 	for i := range c {
 		log.Printf("%s (%s)\n", c[i].Name(), c[i].State())
+		c[i].Release()
 	}
 
 	log.Println()
@@ -35,6 +36,7 @@ func main() {
 	c = lxc.ActiveContainers(lxcpath)
 	for i := range c {
 		log.Printf("%s (%s)\n", c[i].Name(), c[i].State())
+		c[i].Release()
 	}
 
 	log.Println()
@@ -43,5 +45,6 @@ func main() {
 	c = lxc.ActiveContainers(lxcpath)
 	for i := range c {
 		log.Printf("%s (%s)\n", c[i].Name(), c[i].State())
+		c[i].Release()
 	}
 }
diff --git a/examples/list_keys.go b/examples/list_keys/list_keys.go
similarity index 97%
rename from examples/list_keys.go
rename to examples/list_keys/list_keys.go
index 18bbaa0..90d37d4 100644
--- a/examples/list_keys.go
+++ b/examples/list_keys/list_keys.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	for _, k := range c.ConfigKeys() {
 		log.Printf("%s -> %s", k, c.ConfigItem(k))
diff --git a/examples/list_snapshots.go b/examples/list_snapshots/list_snapshots.go
similarity index 97%
rename from examples/list_snapshots.go
rename to examples/list_snapshots/list_snapshots.go
index 640dff5..8ed2359 100644
--- a/examples/list_snapshots.go
+++ b/examples/list_snapshots/list_snapshots.go
@@ -28,5 +28,6 @@ func main() {
 			log.Printf("LXC path: %s\n", s.Path)
 			log.Println()
 		}
+		c[i].Release()
 	}
 }
diff --git a/examples/reboot.go b/examples/reboot/reboot.go
similarity index 97%
rename from examples/reboot.go
rename to examples/reboot/reboot.go
index 78133d0..db4c5ad 100644
--- a/examples/reboot.go
+++ b/examples/reboot/reboot.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Rebooting the container...\n")
 	if err := c.Reboot(); err != nil {
diff --git a/examples/rename.go b/examples/rename/rename.go
similarity index 97%
rename from examples/rename.go
rename to examples/rename/rename.go
index 4c4a4b3..8212dcf 100644
--- a/examples/rename.go
+++ b/examples/rename/rename.go
@@ -31,6 +31,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Renaming container to %s...\n", newname)
 	if err := c.Rename(newname); err != nil {
diff --git a/examples/restore_snapshot.go b/examples/restore_snapshot/restore_snapshot.go
similarity index 97%
rename from examples/restore_snapshot.go
rename to examples/restore_snapshot/restore_snapshot.go
index feb5cc6..3be2972 100644
--- a/examples/restore_snapshot.go
+++ b/examples/restore_snapshot/restore_snapshot.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Restoring the container...\n")
 	snapshot := lxc.Snapshot{Name: "snap0"}
diff --git a/examples/shutdown.go b/examples/shutdown/shutdown.go
similarity index 97%
rename from examples/shutdown.go
rename to examples/shutdown/shutdown.go
index b361aaf..5ef712c 100644
--- a/examples/shutdown.go
+++ b/examples/shutdown/shutdown.go
@@ -30,6 +30,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Shutting down the container...\n")
 	if err := c.Shutdown(30 * time.Second); err != nil {
diff --git a/examples/start.go b/examples/start/start.go
similarity index 98%
rename from examples/start.go
rename to examples/start/start.go
index 7005c17..4e26f1f 100644
--- a/examples/start.go
+++ b/examples/start/start.go
@@ -30,6 +30,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	c.SetLogFile("/tmp/" + name + ".log")
 	c.SetLogLevel(lxc.TRACE)
diff --git a/examples/stats.go b/examples/stats/stats.go
similarity index 99%
rename from examples/stats.go
rename to examples/stats/stats.go
index b1ee53f..7a3bd6f 100644
--- a/examples/stats.go
+++ b/examples/stats/stats.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	// mem
 	memUsed, err := c.MemoryUsage()
diff --git a/examples/stop.go b/examples/stop/stop.go
similarity index 97%
rename from examples/stop.go
rename to examples/stop/stop.go
index 2ec77c8..f95ff53 100644
--- a/examples/stop.go
+++ b/examples/stop/stop.go
@@ -29,6 +29,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	c.SetLogFile("/tmp/" + name + ".log")
 	c.SetLogLevel(lxc.TRACE)
diff --git a/examples/unfreeze.go b/examples/unfreeze/unfreeze.go
similarity index 97%
rename from examples/unfreeze.go
rename to examples/unfreeze/unfreeze.go
index 1f4d08e..bf7905f 100644
--- a/examples/unfreeze.go
+++ b/examples/unfreeze/unfreeze.go
@@ -30,6 +30,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("ERROR: %s\n", err.Error())
 	}
+	defer c.Release()
 
 	log.Printf("Unfreezing the container...\n")
 	if err := c.Unfreeze(); err != nil {
diff --git a/linking_dynamic.go b/linking_dynamic.go
new file mode 100644
index 0000000..1197b81
--- /dev/null
+++ b/linking_dynamic.go
@@ -0,0 +1,10 @@
+// Copyright © 2013, 2014, The Go-LXC Authors. All rights reserved.
+// Use of this source code is governed by a LGPLv2.1
+// license that can be found in the LICENSE file.
+
+// +build linux,cgo,!static_build
+
+package lxc
+
+// #cgo LDFLAGS: -llxc -lutil
+import "C"
diff --git a/linking_static.go b/linking_static.go
new file mode 100644
index 0000000..89f06b4
--- /dev/null
+++ b/linking_static.go
@@ -0,0 +1,10 @@
+// Copyright © 2013, 2014, The Go-LXC Authors. All rights reserved.
+// Use of this source code is governed by a LGPLv2.1
+// license that can be found in the LICENSE file.
+
+// +build linux,cgo,static_build
+
+package lxc
+
+// #cgo LDFLAGS: -static -llxc -lseccomp -lutil -lcap
+import "C"
diff --git a/lxc-binding.c b/lxc-binding.c
index 7e408c0..51d6a9a 100644
--- a/lxc-binding.c
+++ b/lxc-binding.c
@@ -5,6 +5,7 @@
 // +build linux,cgo
 
 #include <stdbool.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <errno.h>
@@ -52,6 +53,9 @@ bool go_lxc_want_close_all_fds(struct lxc_container *c, bool state) {
 }
 
 bool go_lxc_create(struct lxc_container *c, const char *t, const char *bdevtype, int flags, char * const argv[]) {
+	if (strncmp(t, "none", strlen(t)) == 0) {
+		return c->create(c, NULL, bdevtype, NULL, !!(flags & LXC_CREATE_QUIET), argv);
+	}
 	return c->create(c, t, bdevtype, NULL, !!(flags & LXC_CREATE_QUIET), argv);
 }
 
@@ -191,7 +195,12 @@ bool go_lxc_save_config(struct lxc_container *c, const char *alt_file) {
 }
 
 bool go_lxc_clone(struct lxc_container *c, const char *newname, const char *lxcpath, int flags, const char *bdevtype) {
-	return c->clone(c, newname, lxcpath, flags, bdevtype, NULL, 0, NULL) != NULL;
+	struct lxc_container *c2 = c->clone(c, newname, lxcpath, flags, bdevtype, NULL, 0, NULL);
+	if (c2 == NULL) {
+		return false;
+	}
+	lxc_container_put(c2);
+	return true;
 }
 
 int go_lxc_console_getfd(struct lxc_container *c, int ttynum) {
diff --git a/lxc-binding.go b/lxc-binding.go
index 3cd38d6..61462a1 100644
--- a/lxc-binding.go
+++ b/lxc-binding.go
@@ -7,7 +7,6 @@
 package lxc
 
 // #cgo pkg-config: lxc
-// #cgo LDFLAGS: -llxc -lutil
 // #include <lxc/lxccontainer.h>
 // #include <lxc/version.h>
 // #include "lxc-binding.h"
@@ -18,13 +17,13 @@ import "C"
 
 import (
 	"fmt"
-	"runtime"
 	"strconv"
 	"strings"
 	"unsafe"
 )
 
 // NewContainer returns a new container struct.
+// Caller needs to call Release() on the returned container to release its resources.
 func NewContainer(name string, lxcpath ...string) (*Container, error) {
 	var container *C.struct_lxc_container
 
@@ -45,8 +44,6 @@ func NewContainer(name string, lxcpath ...string) (*Container, error) {
 	}
 	c := &Container{container: container, verbosity: Quiet}
 
-	// http://golang.org/pkg/runtime/#SetFinalizer
-	runtime.SetFinalizer(c, Release)
 	return c, nil
 }
 
@@ -57,13 +54,10 @@ func Acquire(c *Container) bool {
 
 // Release decrements the reference counter of the container object.
 func Release(c *Container) bool {
-	// http://golang.org/pkg/runtime/#SetFinalizer
-	runtime.SetFinalizer(c, nil)
-
-	// Go is bad at refcounting sometimes
-	c.mu.Lock()
-
-	return C.lxc_container_put(c.container) == 1
+	if C.lxc_container_put(c.container) == -1 {
+		return false
+	}
+	return true
 }
 
 // Version returns the LXC version.
@@ -124,6 +118,7 @@ func ContainerNames(lxcpath ...string) []string {
 
 // Containers returns the defined and active containers on the system. Only
 // containers that could retrieved successfully are returned.
+// Caller needs to call Release() on the returned containers to release resources.
 func Containers(lxcpath ...string) []*Container {
 	var containers []*Container
 
@@ -159,6 +154,7 @@ func DefinedContainerNames(lxcpath ...string) []string {
 
 // DefinedContainers returns the defined containers on the system.  Only
 // containers that could retrieved successfully are returned.
+// Caller needs to call Release() on the returned containers to release resources.
 func DefinedContainers(lxcpath ...string) []*Container {
 	var containers []*Container
 
@@ -194,6 +190,7 @@ func ActiveContainerNames(lxcpath ...string) []string {
 
 // ActiveContainers returns the active containers on the system. Only
 // containers that could retrieved successfully are returned.
+// Caller needs to call Release() on the returned containers to release resources.
 func ActiveContainers(lxcpath ...string) []*Container {
 	var containers []*Container
 
diff --git a/lxc_test.go b/lxc_test.go
index 3e8d3b5..4494f5c 100644
--- a/lxc_test.go
+++ b/lxc_test.go
@@ -8,7 +8,9 @@ package lxc
 
 import (
 	"fmt"
+	"io/ioutil"
 	"math/rand"
+	"net"
 	"os"
 	"runtime"
 	"strconv"
@@ -20,15 +22,15 @@ import (
 )
 
 const (
-	ContainerName             = "lorem"
-	SnapshotName              = "snap0"
-	ContainerRestoreName      = "ipsum"
-	ContainerCloneName        = "consectetur"
-	ContainerCloneOverlayName = "adipiscing"
-	ContainerCloneAufsName    = "pellentesque"
+	DefaultContainerName             = "lorem"
+	DefaultSnapshotName              = "snap0"
+	DefaultContainerRestoreName      = "ipsum"
+	DefaultContainerCloneName        = "consectetur"
+	DefaultContainerCloneOverlayName = "adipiscing"
+	DefaultContainerCloneAufsName    = "pellentesque"
 )
 
-func PathExists(name string) bool {
+func exists(name string) bool {
 	_, err := os.Lstat(name)
 	if err != nil && os.IsNotExist(err) {
 		return false
@@ -40,6 +42,11 @@ func unprivileged() bool {
 	return os.Geteuid() != 0
 }
 
+func travis() bool {
+	// https://docs.travis-ci.com/user/environment-variables/#default-environment-variables
+	return os.Getenv("TRAVIS") == "true"
+}
+
 func supported(moduleName string) bool {
 	if _, err := os.Stat("/sys/module/" + moduleName); err != nil {
 		return false
@@ -47,6 +54,76 @@ func supported(moduleName string) bool {
 	return true
 }
 
+func ipv6() bool {
+	lxcbr0, err := net.InterfaceByName("lxcbr0")
+	if err != nil {
+		return false
+	}
+
+	addresses, err := lxcbr0.Addrs()
+	if err != nil {
+		return false
+	}
+
+	// https://github.com/asaskevich/govalidator/blob/master/validator.go#L621
+	for _, v := range addresses {
+		if ipnet, ok := v.(*net.IPNet); ok && strings.Count(v.String(), ":") >= 2 && !ipnet.IP.IsLinkLocalUnicast() {
+			return true
+		}
+	}
+
+	return false
+}
+
+func template() TemplateOptions {
+	if !unprivileged() {
+		return BusyboxTemplateOptions
+	}
+
+	// travis uses trusy which comes with lxc 1.0.x so use a compatible image
+	return TemplateOptions{
+		Template: "download",
+		Distro:   "ubuntu",
+		Release:  "trusty",
+		Arch:     "amd64",
+	}
+}
+
+func ContainerName() string {
+	if unprivileged() {
+		return fmt.Sprintf("%s-unprivileged", DefaultContainerName)
+	}
+	return DefaultContainerName
+}
+
+func ContainerRestoreName() string {
+	if unprivileged() {
+		return fmt.Sprintf("%s-unprivileged", DefaultContainerRestoreName)
+	}
+	return DefaultContainerRestoreName
+}
+
+func ContainerCloneName() string {
+	if unprivileged() {
+		return fmt.Sprintf("%s-unprivileged", DefaultContainerCloneName)
+	}
+	return DefaultContainerCloneName
+}
+
+func ContainerCloneOverlayName() string {
+	if unprivileged() {
+		return fmt.Sprintf("%s-unprivileged", DefaultContainerCloneOverlayName)
+	}
+	return DefaultContainerCloneOverlayName
+}
+
+func ContainerCloneAufsName() string {
+	if unprivileged() {
+		return fmt.Sprintf("%s-unprivileged", DefaultContainerCloneAufsName)
+	}
+	return DefaultContainerCloneAufsName
+}
+
 func TestVersion(t *testing.T) {
 	t.Logf("LXC version: %s", Version())
 }
@@ -58,10 +135,11 @@ func TestDefaultConfigPath(t *testing.T) {
 }
 
 func TestSetConfigPath(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	currentPath := c.ConfigPath()
 	if err := c.SetConfigPath("/tmp"); err != nil {
@@ -75,10 +153,11 @@ func TestSetConfigPath(t *testing.T) {
 }
 
 func TestAcquire(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	Acquire(c)
 	Release(c)
@@ -96,6 +175,7 @@ func TestConcurrentDefined_Negative(t *testing.T) {
 			if err != nil {
 				t.Errorf(err.Error())
 			}
+			defer c.Release()
 
 			// sleep for a while to simulate some dummy work
 			time.Sleep(time.Millisecond * time.Duration(rand.Intn(250)))
@@ -110,10 +190,11 @@ func TestConcurrentDefined_Negative(t *testing.T) {
 }
 
 func TestDefined_Negative(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if c.Defined() {
 		t.Errorf("Defined_Negative failed...")
@@ -125,10 +206,11 @@ func TestExecute(t *testing.T) {
 		t.Skip("skipping test in unprivileged mode.")
 	}
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.Execute("/bin/true"); err != nil {
 		t.Errorf(err.Error())
@@ -136,47 +218,53 @@ func TestExecute(t *testing.T) {
 }
 
 func TestSetVerbosity(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	c.SetVerbosity(Quiet)
 }
 
 func TestCreate(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	if err := c.Create(BusyboxTemplateOptions); err != nil {
+	c.SetVerbosity(Verbose)
+
+	if err := c.Create(template()); err != nil {
 		t.Errorf(err.Error())
 	}
 }
 
 func TestClone(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	if err = c.Clone(ContainerCloneName, DefaultCloneOptions); err != nil {
+	if err = c.Clone(ContainerCloneName(), DefaultCloneOptions); err != nil {
 		t.Errorf(err.Error())
 	}
 }
 
 func TestCloneUsingOverlayfs(t *testing.T) {
-	if !supported("overlayfs") {
+	if !(supported("overlayfs") || supported("overlay")) {
 		t.Skip("skipping test as overlayfs support is missing.")
 	}
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	err = c.Clone(ContainerCloneOverlayName, CloneOptions{
+	err = c.Clone(ContainerCloneOverlayName(), CloneOptions{
 		Backend:  Overlayfs,
 		KeepName: true,
 		KeepMAC:  true,
@@ -196,12 +284,13 @@ func TestCloneUsingAufs(t *testing.T) {
 		t.Skip("skipping test as aufs support is missing.")
 	}
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	err = c.Clone(ContainerCloneAufsName, CloneOptions{
+	err = c.Clone(ContainerCloneAufsName(), CloneOptions{
 		Backend:  Aufs,
 		KeepName: true,
 		KeepMAC:  true,
@@ -213,10 +302,11 @@ func TestCloneUsingAufs(t *testing.T) {
 }
 
 func TestCreateSnapshot(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.CreateSnapshot(); err != nil {
 		t.Errorf(err.Error())
@@ -224,10 +314,11 @@ func TestCreateSnapshot(t *testing.T) {
 }
 
 func TestCreateSnapshots(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	for i := 0; i < 3; i++ {
 		if _, err := c.CreateSnapshot(); err != nil {
@@ -237,13 +328,14 @@ func TestCreateSnapshots(t *testing.T) {
 }
 
 func TestRestoreSnapshot(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	snapshot := Snapshot{Name: SnapshotName}
-	if err := c.RestoreSnapshot(snapshot, ContainerRestoreName); err != nil {
+	snapshot := Snapshot{Name: DefaultSnapshotName}
+	if err := c.RestoreSnapshot(snapshot, ContainerRestoreName()); err != nil {
 		t.Errorf(err.Error())
 	}
 }
@@ -257,7 +349,7 @@ func TestConcurrentCreate(t *testing.T) {
 
 	var wg sync.WaitGroup
 
-	options := BusyboxTemplateOptions
+	options := template()
 	for i := 0; i < 10; i++ {
 		wg.Add(1)
 		go func(i int) {
@@ -265,6 +357,7 @@ func TestConcurrentCreate(t *testing.T) {
 			if err != nil {
 				t.Errorf(err.Error())
 			}
+			defer c.Release()
 
 			// sleep for a while to simulate some dummy work
 			time.Sleep(time.Millisecond * time.Duration(rand.Intn(250)))
@@ -279,10 +372,11 @@ func TestConcurrentCreate(t *testing.T) {
 }
 
 func TestSnapshots(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.Snapshots(); err != nil {
 		t.Errorf(err.Error())
@@ -305,6 +399,7 @@ func TestConcurrentStart(t *testing.T) {
 			if err != nil {
 				t.Errorf(err.Error())
 			}
+			defer c.Release()
 
 			if err := c.Start(); err != nil {
 				t.Errorf(err.Error())
@@ -322,10 +417,11 @@ func TestConcurrentStart(t *testing.T) {
 }
 
 func TestConfigFileName(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if c.ConfigFileName() == "" {
 		t.Errorf("ConfigFileName failed...")
@@ -333,10 +429,11 @@ func TestConfigFileName(t *testing.T) {
 }
 
 func TestDefined_Positive(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if !c.Defined() {
 		t.Errorf("Defined_Positive failed...")
@@ -359,6 +456,7 @@ func TestConcurrentDefined_Positive(t *testing.T) {
 			if err != nil {
 				t.Errorf(err.Error())
 			}
+			defer c.Release()
 
 			// sleep for a while to simulate some dummy work
 			time.Sleep(time.Millisecond * time.Duration(rand.Intn(250)))
@@ -373,10 +471,11 @@ func TestConcurrentDefined_Positive(t *testing.T) {
 }
 
 func TestInitPid_Negative(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if c.InitPid() != -1 {
 		t.Errorf("InitPid failed...")
@@ -384,10 +483,16 @@ func TestInitPid_Negative(t *testing.T) {
 }
 
 func TestStart(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
+
+	log := fmt.Sprintf("/tmp/%s", ContainerName())
+	if err := c.SetLogFile(log); err != nil {
+		t.Errorf("SetLogFile failed...")
+	}
 
 	if err := c.Start(); err != nil {
 		t.Errorf(err.Error())
@@ -396,6 +501,12 @@ func TestStart(t *testing.T) {
 	c.Wait(RUNNING, 30*time.Second)
 	if !c.Running() {
 		t.Errorf("Starting the container failed...")
+
+		b, err := ioutil.ReadFile(log)
+		if err != nil {
+			t.Errorf("Reading %s file failed...", log)
+		}
+		t.Logf("%s\n", b)
 	}
 }
 
@@ -404,10 +515,11 @@ func TestWaitIPAddresses(t *testing.T) {
 		t.Skip("skipping test in privileged mode.")
 	}
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.WaitIPAddresses(30 * time.Second); err != nil {
 		t.Errorf(err.Error())
@@ -415,13 +527,14 @@ func TestWaitIPAddresses(t *testing.T) {
 }
 
 func TestControllable(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if !c.Controllable() {
-		t.Errorf("Controling the container failed...")
+		t.Errorf("Controlling the container failed...")
 	}
 }
 
@@ -462,10 +575,11 @@ func TestActiveContainers(t *testing.T) {
 }
 
 func TestRunning(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if !c.Running() {
 		t.Errorf("Checking the container failed...")
@@ -473,10 +587,11 @@ func TestRunning(t *testing.T) {
 }
 
 func TestWantDaemonize(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.WantDaemonize(false); err != nil || c.Daemonize() {
 		t.Errorf("WantDaemonize failed...")
@@ -484,10 +599,11 @@ func TestWantDaemonize(t *testing.T) {
 }
 
 func TestWantCloseAllFds(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.WantCloseAllFds(true); err != nil {
 		t.Errorf("WantCloseAllFds failed...")
@@ -495,10 +611,11 @@ func TestWantCloseAllFds(t *testing.T) {
 }
 
 func TestSetLogLevel(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.SetLogLevel(WARN); err != nil || c.LogLevel() != WARN {
 		t.Errorf("SetLogLevel( failed...")
@@ -506,21 +623,23 @@ func TestSetLogLevel(t *testing.T) {
 }
 
 func TestSetLogFile(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	if err := c.SetLogFile("/tmp/" + ContainerName); err != nil || c.LogFile() != "/tmp/"+ContainerName {
+	if err := c.SetLogFile("/tmp/" + ContainerName()); err != nil || c.LogFile() != "/tmp/"+ContainerName() {
 		t.Errorf("SetLogFile failed...")
 	}
 }
 
 func TestInitPid_Positive(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if c.InitPid() == -1 {
 		t.Errorf("InitPid failed...")
@@ -528,21 +647,23 @@ func TestInitPid_Positive(t *testing.T) {
 }
 
 func TestName(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	if c.Name() != ContainerName {
+	if c.Name() != ContainerName() {
 		t.Errorf("Name failed...")
 	}
 }
 
 func TestFreeze(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.Freeze(); err != nil {
 		t.Errorf(err.Error())
@@ -555,10 +676,11 @@ func TestFreeze(t *testing.T) {
 }
 
 func TestUnfreeze(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.Unfreeze(); err != nil {
 		t.Errorf(err.Error())
@@ -571,10 +693,11 @@ func TestUnfreeze(t *testing.T) {
 }
 
 func TestLoadConfigFile(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.LoadConfigFile(c.ConfigFileName()); err != nil {
 		t.Errorf(err.Error())
@@ -582,10 +705,11 @@ func TestLoadConfigFile(t *testing.T) {
 }
 
 func TestSaveConfigFile(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.SaveConfigFile(c.ConfigFileName()); err != nil {
 		t.Errorf(err.Error())
@@ -593,36 +717,39 @@ func TestSaveConfigFile(t *testing.T) {
 }
 
 func TestConfigItem(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	if c.ConfigItem("lxc.utsname")[0] != ContainerName {
+	if c.ConfigItem("lxc.utsname")[0] != ContainerName() {
 		t.Errorf("ConfigItem failed...")
 	}
 }
 
 func TestSetConfigItem(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	if err := c.SetConfigItem("lxc.utsname", ContainerName); err != nil {
+	if err := c.SetConfigItem("lxc.utsname", ContainerName()); err != nil {
 		t.Errorf(err.Error())
 	}
 
-	if c.ConfigItem("lxc.utsname")[0] != ContainerName {
+	if c.ConfigItem("lxc.utsname")[0] != ContainerName() {
 		t.Errorf("ConfigItem failed...")
 	}
 }
 
 func TestRunningConfigItem(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if c.RunningConfigItem("lxc.network.0.type") == nil {
 		t.Errorf("RunningConfigItem failed...")
@@ -630,10 +757,11 @@ func TestRunningConfigItem(t *testing.T) {
 }
 
 func TestSetCgroupItem(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	maxMem := c.CgroupItem("memory.max_usage_in_bytes")[0]
 	currentMem := c.CgroupItem("memory.limit_in_bytes")[0]
@@ -648,10 +776,11 @@ func TestSetCgroupItem(t *testing.T) {
 }
 
 func TestClearConfigItem(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.ClearConfigItem("lxc.cap.drop"); err != nil {
 		t.Errorf(err.Error())
@@ -662,10 +791,11 @@ func TestClearConfigItem(t *testing.T) {
 }
 
 func TestConfigKeys(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	keys := ""
 	if VersionAtLeast(2, 1, 0) {
@@ -680,10 +810,11 @@ func TestConfigKeys(t *testing.T) {
 }
 
 func TestInterfaces(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.Interfaces(); err != nil {
 		t.Errorf(err.Error())
@@ -691,10 +822,11 @@ func TestInterfaces(t *testing.T) {
 }
 
 func TestInterfaceStats(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.InterfaceStats(); err != nil {
 		t.Errorf(err.Error())
@@ -702,10 +834,11 @@ func TestInterfaceStats(t *testing.T) {
 }
 
 func TestMemoryUsage(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.MemoryUsage(); err != nil {
 		t.Errorf(err.Error())
@@ -713,10 +846,11 @@ func TestMemoryUsage(t *testing.T) {
 }
 
 func TestKernelMemoryUsage(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.KernelMemoryUsage(); err != nil {
 		t.Errorf(err.Error())
@@ -724,14 +858,15 @@ func TestKernelMemoryUsage(t *testing.T) {
 }
 
 func TestMemorySwapUsage(t *testing.T) {
-	if !PathExists("/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes") {
+	if !exists("/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes") {
 		t.Skip("skipping the test as it requires memory.memsw.limit_in_bytes to be set")
 	}
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.MemorySwapUsage(); err != nil {
 		t.Errorf(err.Error())
@@ -739,10 +874,11 @@ func TestMemorySwapUsage(t *testing.T) {
 }
 
 func TestBlkioUsage(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.BlkioUsage(); err != nil {
 		t.Errorf(err.Error())
@@ -750,10 +886,11 @@ func TestBlkioUsage(t *testing.T) {
 }
 
 func TestMemoryLimit(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.MemoryLimit(); err != nil {
 		t.Errorf(err.Error())
@@ -761,10 +898,11 @@ func TestMemoryLimit(t *testing.T) {
 }
 
 func TestSoftMemoryLimit(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.SoftMemoryLimit(); err != nil {
 		t.Errorf(err.Error())
@@ -772,10 +910,11 @@ func TestSoftMemoryLimit(t *testing.T) {
 }
 
 func TestKernelMemoryLimit(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.KernelMemoryLimit(); err != nil {
 		t.Errorf(err.Error())
@@ -783,14 +922,15 @@ func TestKernelMemoryLimit(t *testing.T) {
 }
 
 func TestMemorySwapLimit(t *testing.T) {
-	if !PathExists("/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes") {
+	if !exists("/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes") {
 		t.Skip("skipping the test as it requires memory.memsw.limit_in_bytes to be set")
 	}
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.MemorySwapLimit(); err != nil {
 		t.Errorf(err.Error())
@@ -798,10 +938,11 @@ func TestMemorySwapLimit(t *testing.T) {
 }
 
 func TestSetMemoryLimit(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	oldMemLimit, err := c.MemoryLimit()
 	if err != nil {
@@ -823,10 +964,11 @@ func TestSetMemoryLimit(t *testing.T) {
 }
 
 func TestSetSoftMemoryLimit(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	oldMemLimit, err := c.MemoryLimit()
 	if err != nil {
@@ -850,10 +992,11 @@ func TestSetSoftMemoryLimit(t *testing.T) {
 func TestSetKernelMemoryLimit(t *testing.T) {
 	t.Skip("skipping the test as it requires memory.kmem.limit_in_bytes to be set")
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	oldMemLimit, err := c.KernelMemoryLimit()
 	if err != nil {
@@ -876,14 +1019,15 @@ func TestSetKernelMemoryLimit(t *testing.T) {
 }
 
 func TestSetMemorySwapLimit(t *testing.T) {
-	if !PathExists("/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes") {
+	if !exists("/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes") {
 		t.Skip("skipping the test as it requires memory.memsw.limit_in_bytes to be set")
 	}
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	oldMemorySwapLimit, err := c.MemorySwapLimit()
 	if err != nil {
@@ -905,10 +1049,11 @@ func TestSetMemorySwapLimit(t *testing.T) {
 }
 
 func TestCPUTime(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.CPUTime(); err != nil {
 		t.Errorf(err.Error())
@@ -916,10 +1061,11 @@ func TestCPUTime(t *testing.T) {
 }
 
 func TestCPUTimePerCPU(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.CPUTimePerCPU(); err != nil {
 		t.Errorf(err.Error())
@@ -927,10 +1073,11 @@ func TestCPUTimePerCPU(t *testing.T) {
 }
 
 func TestCPUStats(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.CPUStats(); err != nil {
 		t.Errorf(err.Error())
@@ -943,8 +1090,9 @@ func TestRunCommandNoWait(t *testing.T) {
 		t.Errorf(err.Error())
 		t.FailNow()
 	}
+	defer c.Release()
 
-	if err := c.Create(BusyboxTemplateOptions); err != nil {
+	if err := c.Create(template()); err != nil {
 		t.Errorf(err.Error())
 		t.FailNow()
 	}
@@ -1006,10 +1154,11 @@ func TestRunCommandNoWait(t *testing.T) {
 }
 
 func TestRunCommand(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	argsThree := []string{"/bin/sh", "-c", "exit 0"}
 	ok, err := c.RunCommand(argsThree, DefaultAttachOptions)
@@ -1031,10 +1180,11 @@ func TestRunCommand(t *testing.T) {
 }
 
 func TestCommandWithEnv(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	options := DefaultAttachOptions
 	options.Env = []string{"FOO=BAR"}
@@ -1051,10 +1201,11 @@ func TestCommandWithEnv(t *testing.T) {
 }
 
 func TestCommandWithEnvToKeep(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	options := DefaultAttachOptions
 	options.ClearEnv = true
@@ -1071,10 +1222,11 @@ func TestCommandWithEnvToKeep(t *testing.T) {
 }
 
 func TestCommandWithCwd(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	options := DefaultAttachOptions
 	options.Cwd = "/tmp"
@@ -1090,10 +1242,11 @@ func TestCommandWithCwd(t *testing.T) {
 }
 
 func TestCommandWithUIDGID(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	options := DefaultAttachOptions
 	options.UID = 1000
@@ -1127,10 +1280,11 @@ func TestCommandWithArch(t *testing.T) {
 		t.Skip("skipping architecture test, not on x86")
 	}
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	options := DefaultAttachOptions
 	options.Arch = X86
@@ -1146,10 +1300,11 @@ func TestCommandWithArch(t *testing.T) {
 }
 
 func TestConsoleFd(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.ConsoleFd(0); err != nil {
 		t.Errorf(err.Error())
@@ -1157,14 +1312,11 @@ func TestConsoleFd(t *testing.T) {
 }
 
 func TestIPAddress(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
-
-	if unprivileged() {
-		time.Sleep(3 * time.Second)
-	}
+	defer c.Release()
 
 	if _, err := c.IPAddress("lo"); err != nil {
 		t.Errorf(err.Error())
@@ -1172,14 +1324,11 @@ func TestIPAddress(t *testing.T) {
 }
 
 func TestIPv4Address(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
-
-	if unprivileged() {
-		time.Sleep(3 * time.Second)
-	}
+	defer c.Release()
 
 	if _, err := c.IPv4Address("lo"); err != nil {
 		t.Errorf(err.Error())
@@ -1187,14 +1336,15 @@ func TestIPv4Address(t *testing.T) {
 }
 
 func TestIPv46ddress(t *testing.T) {
-	c, err := NewContainer(ContainerName)
-	if err != nil {
-		t.Errorf(err.Error())
+	if !ipv6() {
+		t.Skip("skipping test since lxc bridge does not have ipv6 address")
 	}
 
-	if unprivileged() {
-		time.Sleep(3 * time.Second)
+	c, err := NewContainer(ContainerName())
+	if err != nil {
+		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.IPv6Address("lo"); err != nil {
 		t.Errorf(err.Error())
@@ -1206,10 +1356,15 @@ func TestAddDeviceNode(t *testing.T) {
 		t.Skip("skipping test in unprivileged mode.")
 	}
 
-	c, err := NewContainer(ContainerName)
+	if !exists("/dev/network_latency") {
+		t.Skip("skipping the test as it requires/dev/network_latency")
+	}
+
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.AddDeviceNode("/dev/network_latency"); err != nil {
 		t.Errorf(err.Error())
@@ -1221,10 +1376,15 @@ func TestRemoveDeviceNode(t *testing.T) {
 		t.Skip("skipping test in unprivileged mode.")
 	}
 
-	c, err := NewContainer(ContainerName)
+	if !exists("/dev/network_latency") {
+		t.Skip("skipping the test as it requires/dev/network_latency")
+	}
+
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.RemoveDeviceNode("/dev/network_latency"); err != nil {
 		t.Errorf(err.Error())
@@ -1236,10 +1396,11 @@ func TestIPv4Addresses(t *testing.T) {
 		t.Skip("skipping test in privileged mode.")
 	}
 
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.IPv4Addresses(); err != nil {
 		t.Errorf(err.Error())
@@ -1251,10 +1412,15 @@ func TestIPv6Addresses(t *testing.T) {
 		t.Skip("skipping test in privileged mode.")
 	}
 
-	c, err := NewContainer(ContainerName)
+	if !ipv6() {
+		t.Skip("skipping test since lxc bridge does not have ipv6 address")
+	}
+
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if _, err := c.IPv6Addresses(); err != nil {
 		t.Errorf(err.Error())
@@ -1262,10 +1428,11 @@ func TestIPv6Addresses(t *testing.T) {
 }
 
 func TestReboot(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.Reboot(); err != nil {
 		t.Errorf("Rebooting the container failed...")
@@ -1289,6 +1456,7 @@ func TestConcurrentShutdown(t *testing.T) {
 			if err != nil {
 				t.Errorf(err.Error())
 			}
+			defer c.Release()
 
 			if err := c.Shutdown(30 * time.Second); err != nil {
 				t.Errorf(err.Error())
@@ -1306,10 +1474,11 @@ func TestConcurrentShutdown(t *testing.T) {
 }
 
 func TestShutdown(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.Shutdown(30 * time.Second); err != nil {
 		t.Errorf(err.Error())
@@ -1322,10 +1491,11 @@ func TestShutdown(t *testing.T) {
 }
 
 func TestStop(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.Start(); err != nil {
 		t.Errorf(err.Error())
@@ -1342,22 +1512,24 @@ func TestStop(t *testing.T) {
 }
 
 func TestDestroySnapshot(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
-	snapshot := Snapshot{Name: SnapshotName}
+	snapshot := Snapshot{Name: DefaultSnapshotName}
 	if err := c.DestroySnapshot(snapshot); err != nil {
 		t.Errorf(err.Error())
 	}
 }
 
 func TestDestroyAllSnapshots(t *testing.T) {
-	c, err := NewContainer(ContainerName)
+	c, err := NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.DestroyAllSnapshots(); err != nil {
 		if err == ErrNotSupported {
@@ -1368,11 +1540,12 @@ func TestDestroyAllSnapshots(t *testing.T) {
 }
 
 func TestDestroy(t *testing.T) {
-	if supported("overlayfs") {
-		c, err := NewContainer(ContainerCloneOverlayName)
+	if supported("overlayfs") || supported("overlay") {
+		c, err := NewContainer(ContainerCloneOverlayName())
 		if err != nil {
 			t.Errorf(err.Error())
 		}
+		defer c.Release()
 
 		if err := c.Destroy(); err != nil {
 			t.Errorf(err.Error())
@@ -1380,37 +1553,41 @@ func TestDestroy(t *testing.T) {
 	}
 
 	if !unprivileged() && supported("aufs") {
-		c, err := NewContainer(ContainerCloneAufsName)
+		c, err := NewContainer(ContainerCloneAufsName())
 		if err != nil {
 			t.Errorf(err.Error())
 		}
+		defer c.Release()
 
 		if err := c.Destroy(); err != nil {
 			t.Errorf(err.Error())
 		}
 	}
-	c, err := NewContainer(ContainerCloneName)
+	c, err := NewContainer(ContainerCloneName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.Destroy(); err != nil {
 		t.Errorf(err.Error())
 	}
 
-	c, err = NewContainer(ContainerRestoreName)
+	c, err = NewContainer(ContainerRestoreName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.Destroy(); err != nil {
 		t.Errorf(err.Error())
 	}
 
-	c, err = NewContainer(ContainerName)
+	c, err = NewContainer(ContainerName())
 	if err != nil {
 		t.Errorf(err.Error())
 	}
+	defer c.Release()
 
 	if err := c.Destroy(); err != nil {
 		t.Errorf(err.Error())
@@ -1433,6 +1610,7 @@ func TestConcurrentDestroy(t *testing.T) {
 			if err != nil {
 				t.Errorf(err.Error())
 			}
+			defer c.Release()
 
 			// sleep for a while to simulate some dummy work
 			time.Sleep(time.Millisecond * time.Duration(rand.Intn(250)))
diff --git a/options.go b/options.go
index 23d1bc0..ae6b6fd 100644
--- a/options.go
+++ b/options.go
@@ -200,7 +200,7 @@ type MigrateOptions struct {
 	FeaturesToCheck CriuFeatures
 }
 
-// ConsoleLogOptioins type is used for defining console log options.
+// ConsoleLogOptions type is used for defining console log options.
 type ConsoleLogOptions struct {
 	ClearLog       bool
 	ReadLog        bool