{"id":399523,"date":"2024-06-29T14:43:44","date_gmt":"2024-06-29T14:43:44","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=399523"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-06-29T14:43:44","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=399523","title":{"rendered":"<span>\u042d\u0432\u043e\u043b\u044e\u0446\u0438\u044f Docker. \u0427\u0430\u0441\u0442\u044c 2.1<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/dd3\/257\/105\/dd32571050c43e1910ed0fcd21b26667.jpg\" alt=\"v0.1.0\" title=\"v0.1.0\" width=\"804\" height=\"482\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/dd3\/257\/105\/dd32571050c43e1910ed0fcd21b26667.jpg\" data-blurred=\"true\"\/><figcaption>v0.1.0<\/figcaption><\/figure>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0442\u043e\u0440\u043e\u0439, \u0432 \u0446\u0438\u043a\u043b\u0435 \u043f\u043e \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f \u0438 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044e \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 Docker. \u0412 \u043d\u0435\u0439 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u043b \u0441\u043e\u0431\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0440\u0435\u043b\u0438\u0437 \u043e\u0442 23 \u043c\u0430\u0440\u0442\u0430 2013 \u0433\u043e\u0434\u0430.\u00a0<\/p>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b \u0443\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u0435\u0441\u044c \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b, \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u043d\u044b\u0439 \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438, \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043d\u043e \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0441\u0442\u0430\u043b\u043e \u044f\u0441\u043d\u043e, \u0447\u0442\u043e \u043e\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0435\u0435 \u043d\u0430 \u0434\u0432\u0435. \u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 (2.1) \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430 \u043b\u0438\u0448\u044c \u043e\u0431\u0449\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0438 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434, \u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0447\u0430\u0441\u0442\u044c (2.2) \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0438 \u043a\u043e\u0434\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434. <\/p>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u0430 \u0443\u0436\u0435 \u0431\u044b\u043b\u0438 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043d\u044b \u0432 <a href=\"https:\/\/habr.com\/ru\/post\/573828\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0442\u044b \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u044f, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u043d\u0435\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u044f\u0442\u0438\u043c\u0438\u043d\u0443\u0442\u043d\u043e\u0439 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <a href=\"https:\/\/www.youtube.com\/watch?v=wW9CAH9nSLs\" rel=\"noopener noreferrer nofollow\">The Future of Linux Containers<\/a>, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0438 \u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043f\u0435\u0440\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f Docker.<\/p>\n<h2>Docker v0.1.0  <\/h2>\n<p>\u0412\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f, \u043a\u0430\u043a \u0438 \u0440\u0430\u043d\u0435\u0435, \u043d\u0430 Windows 10 \u0438 Vagrant \u0441 Ubuntu 20.04.\u00a0\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432:<\/p>\n<pre><code class=\"bash\">sudo apt-get update &amp;&amp; sudo apt-get -y install lxc libarchive-tools curl golang git debootstrap tree<\/code><\/pre>\n<p>\u041a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044e v0.1.0:<\/p>\n<pre><code class=\"bash\">cd \/home\/vagrant &amp;&amp; git clone https:\/\/github.com\/docker\/engine.git &amp;&amp; cd .\/engine  git checkout -f v0.1.0 &amp;&amp; git log | head -n 5 &amp;&amp; tree HEAD is now at 57e2126a02 Bumped version to 0.1.0 commit 57e2126a02f8b96b0542df7f6a573233d8419bb1 Author: Solomon Hykes &lt;solomon@dotcloud.com> Date:   Sat Mar 23 17:48:18 2013 -0700      Bumped version to 0.1.0  . \u251c\u2500\u2500 AUTHORS \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 Vagrantfile \u251c\u2500\u2500 archive.go \u251c\u2500\u2500 archive_test.go \u251c\u2500\u2500 auth \u2502   \u251c\u2500\u2500 auth.go \u2502   \u2514\u2500\u2500 auth_test.go \u251c\u2500\u2500 changes.go \u251c\u2500\u2500 commands.go \u251c\u2500\u2500 container.go \u251c\u2500\u2500 container_test.go \u251c\u2500\u2500 contrib \u2502   \u251c\u2500\u2500 README \u2502   \u251c\u2500\u2500 install.sh \u2502   \u2514\u2500\u2500 mkimage-busybox.sh \u251c\u2500\u2500 deb \u2502   \u251c\u2500\u2500 Makefile -> ..\/Makefile \u2502   \u251c\u2500\u2500 Makefile.deb \u2502   \u251c\u2500\u2500 README.md -> ..\/README.md \u2502   \u251c\u2500\u2500 debian \u2502   \u2502   \u251c\u2500\u2500 changelog \u2502   \u2502   \u251c\u2500\u2500 compat \u2502   \u2502   \u251c\u2500\u2500 control \u2502   \u2502   \u251c\u2500\u2500 copyright \u2502   \u2502   \u251c\u2500\u2500 docs \u2502   \u2502   \u251c\u2500\u2500 rules \u2502   \u2502   \u2514\u2500\u2500 source \u2502   \u2502       \u2514\u2500\u2500 format \u2502   \u2514\u2500\u2500 etc \u2502       \u251c\u2500\u2500 docker-dev.upstart \u2502       \u2514\u2500\u2500 docker.upstart \u251c\u2500\u2500 docker \u2502   \u2514\u2500\u2500 docker.go \u251c\u2500\u2500 docs \u2502   \u251c\u2500\u2500 README.md \u2502   \u2514\u2500\u2500 images-repositories-push-pull.md \u251c\u2500\u2500 graph.go \u251c\u2500\u2500 graph_test.go \u251c\u2500\u2500 image.go \u251c\u2500\u2500 lxc_template.go \u251c\u2500\u2500 mount.go \u251c\u2500\u2500 mount_darwin.go \u251c\u2500\u2500 mount_linux.go \u251c\u2500\u2500 network.go \u251c\u2500\u2500 network_test.go \u251c\u2500\u2500 puppet \u2502   \u251c\u2500\u2500 manifests \u2502   \u2502   \u2514\u2500\u2500 quantal64.pp \u2502   \u2514\u2500\u2500 modules \u2502       \u2514\u2500\u2500 docker \u2502           \u251c\u2500\u2500 manifests \u2502           \u2502   \u2514\u2500\u2500 init.pp \u2502           \u2514\u2500\u2500 templates \u2502               \u251c\u2500\u2500 dockerd.conf \u2502               \u2514\u2500\u2500 profile \u251c\u2500\u2500 rcli \u2502   \u251c\u2500\u2500 http.go \u2502   \u251c\u2500\u2500 tcp.go \u2502   \u2514\u2500\u2500 types.go \u251c\u2500\u2500 registry.go \u251c\u2500\u2500 runtime.go \u251c\u2500\u2500 runtime_test.go \u251c\u2500\u2500 state.go \u251c\u2500\u2500 sysinit.go \u251c\u2500\u2500 tags.go \u251c\u2500\u2500 term \u2502   \u251c\u2500\u2500 term.go \u2502   \u251c\u2500\u2500 termios_darwin.go \u2502   \u2514\u2500\u2500 termios_linux.go \u251c\u2500\u2500 utils.go \u2514\u2500\u2500 utils_test.go  16 directories, 58 files <\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u043f\u0440\u0438\u0431\u0430\u0432\u0438\u043b\u043e\u0441\u044c. \u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 deb \u0438 puppet \u043c\u044b \u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0438 \u043d\u0430\u0441 \u043c\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442. <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b:\u00a0<\/p>\n<pre><code class=\"bash\">go mod init github.com\/dotcloud\/docker &amp;&amp; cd docker &amp;&amp; go build docker.go go: creating new go.mod: module github.com\/dotcloud\/docker go: finding github.com\/kr\/pty v1.1.8 go: downloading github.com\/kr\/pty v1.1.8 go: extracting github.com\/kr\/pty v1.1.8 go: downloading github.com\/creack\/pty v1.1.7 go: extracting github.com\/creack\/pty v1.1.7 go: finding github.com\/creack\/pty v1.1.7<\/code><\/pre>\n<pre><code class=\"bash\">vagrant@ubuntu-focal:\/vagrant\/engine\/docker$ sudo .\/docker version docker version Version:0.1.0   vagrant@ubuntu-focal:~\/engine\/docker$ sudo .\/docker help Usage: docker COMMAND [arg...]  A self-sufficient runtime for linux containers.  Commands:     run       Run a command in a container     ps        Display a list of containers     import    Create a new filesystem image from the contents of a tarball     attach    Attach to a running container     commit    Create a new image from a container's changes     history   Show the history of an image     diff      Inspect changes on a container's filesystem     images    List images     info      Display system-wide information     inspect   Return low-level information on a container     kill      Kill a running container     login     Register or Login to the docker registry server     logs      Fetch the logs of a container     port      Lookup the public-facing port which is NAT-ed to PRIVATE_PORT     ps        List containers     pull      Pull an image or a repository to the docker registry server     push      Push an image or a repository to the docker registry server     restart   Restart a running container     rm        Remove a container     rmi       Remove an image     run       Run a command in a new container     start     Start a stopped container     stop      Stop a running container     export    Stream the contents of a container as a tar archive     version   Show the docker version information     wait      Block until a container stops, then print its exit code<\/code><\/pre>\n<p>\u0423\u0436\u0435 \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u043d\u0430\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438, \u043e\u0431\u0440\u0430\u0437\u0430\u043c\u0438, \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439, \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c, \u0441\u0435\u0442\u0435\u0432\u044b\u043c\u0438 \u043f\u043e\u0440\u0442\u0430\u043c\u0438 \u0438 \u0442\u043f.\u00a0<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0437\u0430 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0441 \u0442\u0435\u0445 \u043f\u043e\u0440 \u0444\u043e\u0440\u043c\u0430\u0442 \u0438 \u0441\u0430\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c, \u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0442\u0447 \u0434\u043b\u044f lxc \u0448\u0430\u0431\u043b\u043e\u043d\u0430. \u041d\u043e \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0431\u0440\u0430\u0437 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0443\u0442\u0438\u043b\u0438\u0442\u044b debootstrap, \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u043f\u0430\u0442\u0447, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440. \u0410 \u043f\u043e\u043a\u0430 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044e \u043a\u043e\u0434\u0430.<\/p>\n<h2>Entry point<\/h2>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f main \u0432 \u0444\u0430\u0439\u043b\u0435 docker\/docker.go:<\/p>\n<pre><code class=\"go\">func main() { if docker.SelfPath() == \"\/sbin\/init\" { \/\/ Running in init mode docker.SysInit() return } \/\/ FIXME: Switch d and D ? (to be more sshd like) fl_daemon := flag.Bool(\"d\", false, \"Daemon mode\") fl_debug := flag.Bool(\"D\", false, \"Debug mode\") flag.Parse() rcli.DEBUG_FLAG = *fl_debug if *fl_daemon { if flag.NArg() != 0 { flag.Usage() return } if err := daemon(); err != nil { log.Fatal(err) } } else { if err := runCommand(flag.Args()); err != nil { log.Fatal(err) } } }<\/code><\/pre>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f, \u043a\u0430\u043a \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u0442\u0440\u0430\u043d\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0441 \/sbin\/init. \u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u0431\u0443\u0434\u0435\u0442 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b docker, \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u0447\u043a\u0443 \/sbin\/init, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u043e\u0433\u043e lxc \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f docker.SysInit() \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 sysinit.go \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435. \u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u044b \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u044d\u0442\u0443 \u0447\u0430\u0441\u0442\u044c.<\/p>\n<pre><code class=\"go\">\/\/ Sys Init code \/\/ This code is run INSIDE the container and is responsible for setting \/\/ up the environment before running the actual process func SysInit() { if len(os.Args) &lt;= 1 { fmt.Println(\"You should not invoke docker-init manually\") os.Exit(1) } var u = flag.String(\"u\", \"\", \"username or uid\") var gw = flag.String(\"g\", \"\", \"gateway address\")  flag.Parse()  setupNetworking(*gw) changeUser(*u) executeProgram(flag.Arg(0), flag.Args()) }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0444\u043b\u0430\u0433\u0430 -d, \u0434\u043e\u043a\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0434\u0435\u043c\u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u044f \u043f\u043e \u0441\u0435\u0442\u0435\u0432\u043e\u043c\u0443 \u0441\u043e\u043a\u0435\u0442\u0443 \u0438\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e.<\/p>\n<pre><code class=\"go\">func daemon() error { service, err := docker.NewServer() if err != nil { return err } return rcli.ListenAndServe(\"tcp\", \"127.0.0.1:4242\", service) }<\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f daemon \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 tcp \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 4242, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0447\u0438\u0442\u0430\u0435\u0442 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 json \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u0415\u0433\u043e \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 rcli\/tcp.go:<\/p>\n<pre><code class=\"go\">\/\/ Listen on `addr`, using protocol `proto`, for incoming rcli calls, \/\/ and pass them to `service`. func ListenAndServe(proto, addr string, service Service) error { listener, err := net.Listen(proto, addr) if err != nil { return err } log.Printf(\"Listening for RCLI\/%s on %s\\n\", proto, addr) defer listener.Close() for { if conn, err := listener.Accept(); err != nil { return err } else { go func() { if DEBUG_FLAG { CLIENT_SOCKET = conn } if err := Serve(conn, service); err != nil { log.Printf(\"Error: \" + err.Error() + \"\\n\") fmt.Fprintf(conn, \"Error: \"+err.Error()+\"\\n\") } conn.Close() }() } } return nil }  \/\/ Parse an rcli call on a new connection, and pass it to `service` if it \/\/ is valid. func Serve(conn io.ReadWriter, service Service) error { r := bufio.NewReader(conn) var args []string if line, err := r.ReadString('\\n'); err != nil { return err } else if err := json.Unmarshal([]byte(line), &amp;args); err != nil { return err } else { return call(service, ioutil.NopCloser(r), conn, args...) } return nil }  \/\/ FIXME: For reverse compatibility func call(service Service, stdin io.ReadCloser, stdout io.Writer, args ...string) error { return LocalCall(service, stdin, stdout, args...) }<\/code><\/pre>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u043e\u043a\u0435\u0440\u0430 \u0431\u0435\u0437 \u0444\u043b\u0430\u0433\u0430 -d \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442 \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 runCommand:  <\/p>\n<pre><code class=\"go\">func runCommand(args []string) error { var oldState *term.State var err error if term.IsTerminal(0) &amp;&amp; os.Getenv(\"NORAW\") == \"\" { oldState, err = term.MakeRaw(0) if err != nil { return err } defer term.Restore(0, oldState) } \/\/ FIXME: we want to use unix sockets here, but net.UnixConn doesn't expose \/\/ CloseWrite(), which we need to cleanly signal that stdin is closed without \/\/ closing the connection. \/\/ See http:\/\/code.google.com\/p\/go\/issues\/detail?id=3345 if conn, err := rcli.Call(\"tcp\", \"127.0.0.1:4242\", args...); err == nil { receive_stdout := docker.Go(func() error { _, err := io.Copy(os.Stdout, conn) return err }) send_stdin := docker.Go(func() error { _, err := io.Copy(conn, os.Stdin) if err := conn.CloseWrite(); err != nil { log.Printf(\"Couldn't send EOF: \" + err.Error()) } return err }) if err := &lt;-receive_stdout; err != nil { return err } if !term.IsTerminal(0) { if err := &lt;-send_stdin; err != nil { return err } } } else { service, err := docker.NewServer() if err != nil { return err } if err := rcli.LocalCall(service, os.Stdin, os.Stdout, args...); err != nil { return err } } if oldState != nil { term.Restore(0, oldState) } return nil }<\/code><\/pre>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u0432 raw \u0440\u0435\u0436\u0438\u043c. \u0412\u0435\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u043e\u043c, \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043f\u0430\u043f\u043a\u0435 term.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u0434\u0435\u0442 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u0435\u043c\u043e\u043d\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 rcli.Call \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 rcli\/tcp.go (\u0434\u0435\u043c\u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441 \u0444\u043b\u0430\u0433\u043e\u043c -d):<\/p>\n<pre><code class=\"go\">\/\/ Connect to a remote endpoint using protocol `proto` and address `addr`, \/\/ issue a single call, and return the result. \/\/ `proto` may be \"tcp\", \"unix\", etc. See the `net` package for available protocols. func Call(proto, addr string, args ...string) (*net.TCPConn, error) { cmd, err := json.Marshal(args) if err != nil { return nil, err } conn, err := net.Dial(proto, addr) if err != nil { return nil, err } if _, err := fmt.Fprintln(conn, string(cmd)); err != nil { return nil, err } return conn.(*net.TCPConn), nil }<\/code><\/pre>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0435 \u0443\u0434\u0430\u043b\u0430\u0441\u044c, \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0432\u044b\u0437\u043e\u0432\u0430 LocalCall \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 docker.NewServer,\u00a0\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 commands.go:<\/p>\n<pre><code class=\"go\">func NewServer() (*Server, error) { rand.Seed(time.Now().UTC().UnixNano()) if runtime.GOARCH != \"amd64\" { log.Fatalf(\"The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.\", runtime.GOARCH) } runtime, err := NewRuntime() if err != nil { return nil, err } srv := &amp;Server{ runtime: runtime, } return srv, nil }  type Server struct { runtime *Runtime }<\/code><\/pre>\n<p>\u041c\u044b \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 Server \u0438 Runtime \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0437\u0436\u0435, \u0430 \u0441\u043f\u0435\u0440\u0432\u0430 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e LocalCall \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 rcli\/types.go:<\/p>\n<pre><code class=\"go\">func LocalCall(service Service, stdin io.ReadCloser, stdout io.Writer, args ...string) error { if len(args) == 0 { args = []string{\"help\"} } flags := flag.NewFlagSet(\"main\", flag.ContinueOnError) flags.SetOutput(stdout) flags.Usage = func() { stdout.Write([]byte(service.Help())) } if err := flags.Parse(args); err != nil { return err } cmd := flags.Arg(0) log.Printf(\"%s\\n\", strings.Join(append(append([]string{service.Name()}, cmd), flags.Args()[1:]...), \" \")) if cmd == \"\" { cmd = \"help\" } method := getMethod(service, cmd) if method != nil { return method(stdin, stdout, flags.Args()[1:]...) } return errors.New(\"No such command: \" + cmd) }<\/code><\/pre>\n<p>\u0412 \u043d\u0435\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0440\u0430\u0437\u0431\u043e\u0440 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0439 \u0438\u0437 getMethod, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b Server \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u043f\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443 &#171;Cmd&#187; + MethodName:<\/p>\n<pre><code class=\"go\">func getMethod(service Service, name string) Cmd { if name == \"help\" { return func(stdin io.ReadCloser, stdout io.Writer, args ...string) error { if len(args) == 0 { stdout.Write([]byte(service.Help())) } else { if method := getMethod(service, args[0]); method == nil { return errors.New(\"No such command: \" + args[0]) } else { method(stdin, stdout, \"--help\") } } return nil } } methodName := \"Cmd\" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:]) method, exists := reflect.TypeOf(service).MethodByName(methodName) if !exists { return nil } return func(stdin io.ReadCloser, stdout io.Writer, args ...string) error { ret := method.Func.CallSlice([]reflect.Value{ reflect.ValueOf(service), reflect.ValueOf(stdin), reflect.ValueOf(stdout), reflect.ValueOf(args), })[0].Interface() if ret == nil { return nil } return ret.(error) } }<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043b\u0435\u0436\u0430\u0442 \u0432 \u0444\u0430\u0439\u043b\u0435 commands.go, \u0438\u0445 \u0440\u0430\u0437\u0431\u043e\u0440\u043e\u043c \u043c\u044b \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u0430 \u043f\u043e\u043a\u0430 \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 NewRuntime \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0439 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 docker.NewServer. \u041e\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 runtime.go \u0438 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 Runtime \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c\u0443\u044e \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 Server:<\/p>\n<pre><code class=\"go\">func NewRuntime() (*Runtime, error) { return NewRuntimeFromDirectory(\"\/var\/lib\/docker\") }  func NewRuntimeFromDirectory(root string) (*Runtime, error) { runtime_repo := path.Join(root, \"containers\")  if err := os.MkdirAll(runtime_repo, 0700); err != nil &amp;&amp; !os.IsExist(err) { return nil, err }  g, err := NewGraph(path.Join(root, \"graph\")) if err != nil { return nil, err } repositories, err := NewTagStore(path.Join(root, \"repositories\"), g) if err != nil { return nil, fmt.Errorf(\"Couldn't create Tag store: %s\", err) } netManager, err := newNetworkManager(networkBridgeIface) if err != nil { return nil, err } authConfig, err := auth.LoadConfig(root) if err != nil &amp;&amp; authConfig == nil { \/\/ If the auth file does not exist, keep going return nil, err }  runtime := &amp;Runtime{ root:           root, repository:     runtime_repo, containers:     list.New(), networkManager: netManager, graph:          g, repositories:   repositories, authConfig:     authConfig, }  if err := runtime.restore(); err != nil { return nil, err } return runtime, nil }<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0430\u0441\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0440\u0430\u043d\u044c\u0448\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u043b\u0430\u0441\u044c \u0432 \u0444\u0430\u0439\u043b\u0435 docker.go,\u00a0 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438 \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u0436\u0435 \u0441\u044e\u0434\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0438 \u043d\u043e\u0432\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b:<\/p>\n<ul>\n<li>\n<p>graph (NewGraph) &#8212; \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u043e \u0441\u043b\u043e\u044f\u043c\u0438 \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u043e\u0431\u0440\u0430\u0437\u0430. \u0424\u0430\u0439\u043b graph.go<\/p>\n<\/li>\n<li>\n<p>networkManager (newNetworkManager) &#8212; \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u0435\u0441\u044c \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0441\u0442\u0435\u043a. \u0424\u0430\u0439\u043b network.go<\/p>\n<\/li>\n<li>\n<p>repositories (NewTagStore) &#8212; \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043c\u0435\u0442\u043a\u0430\u043c\u0438 (tags) \u043e\u0431\u0440\u0430\u0437\u043e\u0432. \u0424\u0430\u0439\u043b tags.go<\/p>\n<\/li>\n<li>\n<p>authConfig (auth.LoadConfig) &#8212; \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043e\u0431\u0440\u0430\u0437\u043e\u0432. \u0424\u0430\u0439\u043b auth\/auth.go  <\/p>\n<\/li>\n<\/ul>\n<p>\u0420\u0430\u0431\u043e\u0442\u0443 \u043c\u0435\u0442\u043e\u0434\u0430 restore \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438 \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. \u041f\u0440\u0438\u043d\u0446\u0438\u043f \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u043f\u0440\u0435\u0436\u043d\u0438\u043c, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0441\u043d\u0443\u043b\u0438\u0441\u044c \u043b\u0438\u0448\u044c \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432:<\/p>\n<pre><code class=\"go\">func (runtime *Runtime) restore() error { dir, err := ioutil.ReadDir(runtime.repository) if err != nil { return err } for _, v := range dir { id := v.Name() container, err := runtime.Load(id) if err != nil { Debugf(\"Failed to load container %v: %v\", id, err) continue } Debugf(\"Loaded container %v\", container.Id) } return nil }   func (runtime *Runtime) Load(id string) (*Container, error) { container := &amp;Container{root: runtime.containerRoot(id)} if err := container.FromDisk(); err != nil { return nil, err } if container.Id != id { return container, fmt.Errorf(\"Container %s is stored at %s\", container.Id, id) } if err := runtime.Register(container); err != nil { return nil, err } return container, nil }   func (container *Container) FromDisk() error { data, err := ioutil.ReadFile(container.jsonPath()) if err != nil { return err } \/\/ Load container settings if err := json.Unmarshal(data, container); err != nil { return err } return nil }<\/code><\/pre>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0430\u0442\u0447, \u0442\u0435\u043f\u0435\u0440\u044c \u0436\u0435 \u043c\u0435\u0442\u043e\u0434 Register \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u043d\u0443\u044e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430:<\/p>\n<pre><code class=\"go\">\/\/ Register makes a container object usable by the runtime as &lt;container.Id> func (runtime *Runtime) Register(container *Container) error { if container.runtime != nil || runtime.Exists(container.Id) { return fmt.Errorf(\"Container is already loaded\") } if err := validateId(container.Id); err != nil { return err } container.runtime = runtime \/\/ Setup state lock (formerly in newState() lock := new(sync.Mutex) container.State.stateChangeLock = lock container.State.stateChangeCond = sync.NewCond(lock) \/\/ Attach to stdout and stderr container.stderr = newWriteBroadcaster() container.stdout = newWriteBroadcaster() \/\/ Attach to stdin if container.Config.OpenStdin { container.stdin, container.stdinPipe = io.Pipe() } else { container.stdinPipe = NopWriteCloser(ioutil.Discard) \/\/ Silently drop stdin } \/\/ Setup logging of stdout and stderr to disk if err := runtime.LogToDisk(container.stdout, container.logPath(\"stdout\")); err != nil { return err } if err := runtime.LogToDisk(container.stderr, container.logPath(\"stderr\")); err != nil { return err } \/\/ done runtime.containers.PushBack(container) return nil } <\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b writeBroadcaster, State \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u043d\u0430\u043c \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0430\u0441\u044c \u043b\u0438\u0448\u044c \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0430 \u0434\u043b\u044f stdin:<\/p>\n<pre><code class=\"go\">type nopWriteCloser struct { io.Writer }  func (w *nopWriteCloser) Close() error { return nil }  func NopWriteCloser(w io.Writer) io.WriteCloser { return &amp;nopWriteCloser{w} }<\/code><\/pre>\n<p>\u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 stdout stderr \u0432 \u0444\u0430\u0439\u043b \u043d\u0430 \u0434\u0438\u0441\u043a:<\/p>\n<pre><code class=\"go\">func (container *Container) logPath(name string) string { return path.Join(container.root, fmt.Sprintf(\"%s-%s.log\", container.Id, name)) }  func (runtime *Runtime) LogToDisk(src *writeBroadcaster, dst string) error { log, err := os.OpenFile(dst, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600) if err != nil { return err } src.AddWriter(NopWriteCloser(log)) return nil }<\/code><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c, \u0434\u0443\u043c\u0430\u044e, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043e\u0431\u0449\u0443\u044e \u0447\u0430\u0441\u0442\u044c\u044e \u0438 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a \u0440\u0430\u0437\u0431\u043e\u0440\u0443 \u043a\u043e\u0434\u0430 \u043a\u043e\u043c\u0430\u043d\u0434.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 <a href=\"https:\/\/habr.com\/ru\/post\/575256\/\" rel=\"noopener noreferrer nofollow\">\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438<\/a> \u043c\u044b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438, \u043e\u0431\u0440\u0430\u0437\u0430\u043c\u0438, \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c, \u0441\u0435\u0442\u0435\u0432\u044b\u043c \u0441\u0442\u0435\u043a\u043e\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0431\u0440\u0430\u0437 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043d\u0430 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/574750\/\"> https:\/\/habr.com\/ru\/articles\/574750\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h2>\n<figure class=\"full-width\"><figcaption>v0.1.0<\/figcaption><\/figure>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0442\u043e\u0440\u043e\u0439, \u0432 \u0446\u0438\u043a\u043b\u0435 \u043f\u043e \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f \u0438 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044e \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 Docker. \u0412 \u043d\u0435\u0439 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u043b \u0441\u043e\u0431\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0440\u0435\u043b\u0438\u0437 \u043e\u0442 23 \u043c\u0430\u0440\u0442\u0430 2013 \u0433\u043e\u0434\u0430.\u00a0<\/p>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b \u0443\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u0435\u0441\u044c \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b, \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u043d\u044b\u0439 \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438, \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043d\u043e \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0441\u0442\u0430\u043b\u043e \u044f\u0441\u043d\u043e, \u0447\u0442\u043e \u043e\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0435\u0435 \u043d\u0430 \u0434\u0432\u0435. \u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 (2.1) \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430 \u043b\u0438\u0448\u044c \u043e\u0431\u0449\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0438 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434, \u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0447\u0430\u0441\u0442\u044c (2.2) \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0438 \u043a\u043e\u0434\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434. <\/p>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u0430 \u0443\u0436\u0435 \u0431\u044b\u043b\u0438 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043d\u044b \u0432 <a href=\"https:\/\/habr.com\/ru\/post\/573828\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0442\u044b \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u044f, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u043d\u0435\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u044f\u0442\u0438\u043c\u0438\u043d\u0443\u0442\u043d\u043e\u0439 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <a href=\"https:\/\/www.youtube.com\/watch?v=wW9CAH9nSLs\" rel=\"noopener noreferrer nofollow\">The Future of Linux Containers<\/a>, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0438 \u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043f\u0435\u0440\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f Docker.<\/p>\n<h2>Docker v0.1.0  <\/h2>\n<p>\u0412\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f, \u043a\u0430\u043a \u0438 \u0440\u0430\u043d\u0435\u0435, \u043d\u0430 Windows 10 \u0438 Vagrant \u0441 Ubuntu 20.04.\u00a0\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432:<\/p>\n<pre><code class=\"bash\">sudo apt-get update &amp;&amp; sudo apt-get -y install lxc libarchive-tools curl golang git debootstrap tree<\/code><\/pre>\n<p>\u041a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044e v0.1.0:<\/p>\n<pre><code class=\"bash\">cd \/home\/vagrant &amp;&amp; git clone https:\/\/github.com\/docker\/engine.git &amp;&amp; cd .\/engine  git checkout -f v0.1.0 &amp;&amp; git log | head -n 5 &amp;&amp; tree HEAD is now at 57e2126a02 Bumped version to 0.1.0 commit 57e2126a02f8b96b0542df7f6a573233d8419bb1 Author: Solomon Hykes &lt;solomon@dotcloud.com> Date:   Sat Mar 23 17:48:18 2013 -0700      Bumped version to 0.1.0  . \u251c\u2500\u2500 AUTHORS \u251c\u2500\u2500 LICENSE \u251c\u2500\u2500 NOTICE \u251c\u2500\u2500 README.md \u251c\u2500\u2500 Vagrantfile \u251c\u2500\u2500 archive.go \u251c\u2500\u2500 archive_test.go \u251c\u2500\u2500 auth \u2502   \u251c\u2500\u2500 auth.go \u2502   \u2514\u2500\u2500 auth_test.go \u251c\u2500\u2500 changes.go \u251c\u2500\u2500 commands.go \u251c\u2500\u2500 container.go \u251c\u2500\u2500 container_test.go \u251c\u2500\u2500 contrib \u2502   \u251c\u2500\u2500 README \u2502   \u251c\u2500\u2500 install.sh \u2502   \u2514\u2500\u2500 mkimage-busybox.sh \u251c\u2500\u2500 deb \u2502   \u251c\u2500\u2500 Makefile -> ..\/Makefile \u2502   \u251c\u2500\u2500 Makefile.deb \u2502   \u251c\u2500\u2500 README.md -> ..\/README.md \u2502   \u251c\u2500\u2500 debian \u2502   \u2502   \u251c\u2500\u2500 changelog \u2502   \u2502   \u251c\u2500\u2500 compat \u2502   \u2502   \u251c\u2500\u2500 control \u2502   \u2502   \u251c\u2500\u2500 copyright \u2502   \u2502   \u251c\u2500\u2500 docs \u2502   \u2502   \u251c\u2500\u2500 rules \u2502   \u2502   \u2514\u2500\u2500 source \u2502   \u2502       \u2514\u2500\u2500 format \u2502   \u2514\u2500\u2500 etc \u2502       \u251c\u2500\u2500 docker-dev.upstart \u2502       \u2514\u2500\u2500 docker.upstart \u251c\u2500\u2500 docker \u2502   \u2514\u2500\u2500 docker.go \u251c\u2500\u2500 docs \u2502   \u251c\u2500\u2500 README.md \u2502   \u2514\u2500\u2500 images-repositories-push-pull.md \u251c\u2500\u2500 graph.go \u251c\u2500\u2500 graph_test.go \u251c\u2500\u2500 image.go \u251c\u2500\u2500 lxc_template.go \u251c\u2500\u2500 mount.go \u251c\u2500\u2500 mount_darwin.go \u251c\u2500\u2500 mount_linux.go \u251c\u2500\u2500 network.go \u251c\u2500\u2500 network_test.go \u251c\u2500\u2500 puppet \u2502   \u251c\u2500\u2500 manifests \u2502   \u2502   \u2514\u2500\u2500 quantal64.pp \u2502   \u2514\u2500\u2500 modules \u2502       \u2514\u2500\u2500 docker \u2502           \u251c\u2500\u2500 manifests \u2502           \u2502   \u2514\u2500\u2500 init.pp \u2502           \u2514\u2500\u2500 templates \u2502               \u251c\u2500\u2500 dockerd.conf \u2502               \u2514\u2500\u2500 profile \u251c\u2500\u2500 rcli \u2502   \u251c\u2500\u2500 http.go \u2502   \u251c\u2500\u2500 tcp.go \u2502   \u2514\u2500\u2500 types.go \u251c\u2500\u2500 registry.go \u251c\u2500\u2500 runtime.go \u251c\u2500\u2500 runtime_test.go \u251c\u2500\u2500 state.go \u251c\u2500\u2500 sysinit.go \u251c\u2500\u2500 tags.go \u251c\u2500\u2500 term \u2502   \u251c\u2500\u2500 term.go \u2502   \u251c\u2500\u2500 termios_darwin.go \u2502   \u2514\u2500\u2500 termios_linux.go \u251c\u2500\u2500 utils.go \u2514\u2500\u2500 utils_test.go  16 directories, 58 files <\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u043f\u0440\u0438\u0431\u0430\u0432\u0438\u043b\u043e\u0441\u044c. \u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 deb \u0438 puppet \u043c\u044b \u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0438 \u043d\u0430\u0441 \u043c\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442. <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b:\u00a0<\/p>\n<pre><code class=\"bash\">go mod init github.com\/dotcloud\/docker &amp;&amp; cd docker &amp;&amp; go build docker.go go: creating new go.mod: module github.com\/dotcloud\/docker go: finding github.com\/kr\/pty v1.1.8 go: downloading github.com\/kr\/pty v1.1.8 go: extracting github.com\/kr\/pty v1.1.8 go: downloading github.com\/creack\/pty v1.1.7 go: extracting github.com\/creack\/pty v1.1.7 go: finding github.com\/creack\/pty v1.1.7<\/code><\/pre>\n<pre><code class=\"bash\">vagrant@ubuntu-focal:\/vagrant\/engine\/docker$ sudo .\/docker version docker version Version:0.1.0   vagrant@ubuntu-focal:~\/engine\/docker$ sudo .\/docker help Usage: docker COMMAND [arg...]  A self-sufficient runtime for linux containers.  Commands:     run       Run a command in a container     ps        Display a list of containers     import    Create a new filesystem image from the contents of a tarball     attach    Attach to a running container     commit    Create a new image from a container's changes     history   Show the history of an image     diff      Inspect changes on a container's filesystem     images    List images     info      Display system-wide information     inspect   Return low-level information on a container     kill      Kill a running container     login     Register or Login to the docker registry server     logs      Fetch the logs of a container     port      Lookup the public-facing port which is NAT-ed to PRIVATE_PORT     ps        List containers     pull      Pull an image or a repository to the docker registry server     push      Push an image or a repository to the docker registry server     restart   Restart a running container     rm        Remove a container     rmi       Remove an image     run       Run a command in a new container     start     Start a stopped container     stop      Stop a running container     export    Stream the contents of a container as a tar archive     version   Show the docker version information     wait      Block until a container stops, then print its exit code<\/code><\/pre>\n<p>\u0423\u0436\u0435 \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u043d\u0430\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438, \u043e\u0431\u0440\u0430\u0437\u0430\u043c\u0438, \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439, \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c, \u0441\u0435\u0442\u0435\u0432\u044b\u043c\u0438 \u043f\u043e\u0440\u0442\u0430\u043c\u0438 \u0438 \u0442\u043f.\u00a0<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0437\u0430 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0441 \u0442\u0435\u0445 \u043f\u043e\u0440 \u0444\u043e\u0440\u043c\u0430\u0442 \u0438 \u0441\u0430\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c, \u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0442\u0447 \u0434\u043b\u044f lxc \u0448\u0430\u0431\u043b\u043e\u043d\u0430. \u041d\u043e \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0431\u0440\u0430\u0437 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0443\u0442\u0438\u043b\u0438\u0442\u044b debootstrap, \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u043f\u0430\u0442\u0447, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440. \u0410 \u043f\u043e\u043a\u0430 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044e \u043a\u043e\u0434\u0430.<\/p>\n<h2>Entry point<\/h2>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f main \u0432 \u0444\u0430\u0439\u043b\u0435 docker\/docker.go:<\/p>\n<pre><code class=\"go\">func main() { if docker.SelfPath() == \"\/sbin\/init\" { \/\/ Running in init mode docker.SysInit() return } \/\/ FIXME: Switch d and D ? (to be more sshd like) fl_daemon := flag.Bool(\"d\", false, \"Daemon mode\") fl_debug := flag.Bool(\"D\", false, \"Debug mode\") flag.Parse() rcli.DEBUG_FLAG = *fl_debug if *fl_daemon { if flag.NArg() != 0 { flag.Usage() return } if err := daemon(); err != nil { log.Fatal(err) } } else { if err := runCommand(flag.Args()); err != nil { log.Fatal(err) } } }<\/code><\/pre>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f, \u043a\u0430\u043a \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u0442\u0440\u0430\u043d\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0441 \/sbin\/init. \u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u0431\u0443\u0434\u0435\u0442 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b docker, \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u0447\u043a\u0443 \/sbin\/init, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u043e\u0433\u043e lxc \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f docker.SysInit() \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 sysinit.go \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435. \u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u044b \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u044d\u0442\u0443 \u0447\u0430\u0441\u0442\u044c.<\/p>\n<pre><code class=\"go\">\/\/ Sys Init code \/\/ This code is run INSIDE the container and is responsible for setting \/\/ up the environment before running the actual process func SysInit() { if len(os.Args) &lt;= 1 { fmt.Println(\"You should not invoke docker-init manually\") os.Exit(1) } var u = flag.String(\"u\", \"\", \"username or uid\") var gw = flag.String(\"g\", \"\", \"gateway address\")  flag.Parse()  setupNetworking(*gw) changeUser(*u) executeProgram(flag.Arg(0), flag.Args()) }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0444\u043b\u0430\u0433\u0430 -d, \u0434\u043e\u043a\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0434\u0435\u043c\u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u044f \u043f\u043e \u0441\u0435\u0442\u0435\u0432\u043e\u043c\u0443 \u0441\u043e\u043a\u0435\u0442\u0443 \u0438\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e.<\/p>\n<pre><code class=\"go\">func daemon() error { service, err := docker.NewServer() if err != nil { return err } return rcli.ListenAndServe(\"tcp\", \"127.0.0.1:4242\", service) }<\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f daemon \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 tcp \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 4242, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0447\u0438\u0442\u0430\u0435\u0442 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 json \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u0415\u0433\u043e \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 rcli\/tcp.go:<\/p>\n<pre><code class=\"go\">\/\/ Listen on `addr`, using protocol `proto`, for incoming rcli calls, \/\/ and pass them to `service`. func ListenAndServe(proto, addr string, service Service) error { listener, err := net.Listen(proto, addr) if err != nil { return err } log.Printf(\"Listening for RCLI\/%s on %s\\n\", proto, addr) defer listener.Close() for { if conn, err := listener.Accept(); err != nil { return err } else { go func() { if DEBUG_FLAG { CLIENT_SOCKET = conn } if err := Serve(conn, service); err != nil { log.Printf(\"Error: \" + err.Error() + \"\\n\") fmt.Fprintf(conn, \"Error: \"+err.Error()+\"\\n\") } conn.Close() }() } } return nil }  \/\/ Parse an rcli call on a new connection, and pass it to `service` if it \/\/ is valid. func Serve(conn io.ReadWriter, service Service) error { r := bufio.NewReader(conn) var args []string if line, err := r.ReadString('\\n'); err != nil { return err } else if err := json.Unmarshal([]byte(line), &amp;args); err != nil { return err } else { return call(service, ioutil.NopCloser(r), conn, args...) } return nil }  \/\/ FIXME: For reverse compatibility func call(service Service, stdin io.ReadCloser, stdout io.Writer, args ...string) error { return LocalCall(service, stdin, stdout, args...) }<\/code><\/pre>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u043e\u043a\u0435\u0440\u0430 \u0431\u0435\u0437 \u0444\u043b\u0430\u0433\u0430 -d \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442 \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 runCommand:  <\/p>\n<pre><code class=\"go\">func runCommand(args []string) error { var oldState *term.State var err error if term.IsTerminal(0) &amp;&amp; os.Getenv(\"NORAW\") == \"\" { oldState, err = term.MakeRaw(0) if err != nil { return err } defer term.Restore(0, oldState) } \/\/ FIXME: we want to use unix sockets here, but net.UnixConn doesn't expose \/\/ CloseWrite(), which we need to cleanly signal that stdin is closed without \/\/ closing the connection. \/\/ See http:\/\/code.google.com\/p\/go\/issues\/detail?id=3345 if conn, err := rcli.Call(\"tcp\", \"127.0.0.1:4242\", args...); err == nil { receive_stdout := docker.Go(func() error { _, err := io.Copy(os.Stdout, conn) return err }) send_stdin := docker.Go(func() error { _, err := io.Copy(conn, os.Stdin) if err := conn.CloseWrite(); err != nil { log.Printf(\"Couldn't send EOF: \" + err.Error()) } return err }) if err := &lt;-receive_stdout; err != nil { return err } if !term.IsTerminal(0) { if err := &lt;-send_stdin; err != nil { return err } } } else { service, err := docker.NewServer() if err != nil { return err } if err := rcli.LocalCall(service, os.Stdin, os.Stdout, args...); err != nil { return err } } if oldState != nil { term.Restore(0, oldState) } return nil }<\/code><\/pre>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u0432 raw \u0440\u0435\u0436\u0438\u043c. \u0412\u0435\u0441\u044c<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-399523","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/399523","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=399523"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/399523\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=399523"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=399523"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=399523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}