Skip to content

Latest commit

 

History

History
1027 lines (694 loc) · 69.2 KB

docker.md

File metadata and controls

1027 lines (694 loc) · 69.2 KB

Docker

  • Docker (碼頭工人) 是一種 (software) container platform,定位在 A Better Way to Build Apps;這說法呼應了 Docker 的 logo - 一隻鯨魚做為一個平台 (platform) 並承載了許多貨櫃 (container)
  • 利用 continer 把 app 及 dependencies 打包隔離開來 (isolated),這麼做可以避免衝突並提高安全性,在不同開發階段 (development, testing, deployment) 更提供了 portability 與 predictability,有效免除了 "it works on my machine" 的問題,也就是在解決多人協作時環境不一致的問題。
  • 開發完成後,operator 在佈署多個 app 時,就是在管理多個 isolated container,相對單純許多。

參考資料:

跟 VM 的不同?? {: #vs-vm }

Pricing

  • Docker is Updating and Extending Our Product Subscriptions - Docker Blog (2021-08-31)

    • Docker is used by millions of developers to build, share, and run any app, anywhere, and 55% of professional developers use Docker every day at work. In these work environments, the increase in outside attacks on software SUPPLY CHAINS is accelerating developer demand for Docker’s TRUSTED CONTENT, including Docker Official Images and Docker Verified Publisher images.

      Finally, the rapid global growth in developers – to an estimated 45 million by 2030 – pushes us to SCALE SUSTAINABLY so we may continue to provide an innovative, free Docker experience that developers love.

    • To meet these challenges, today we’re announcing updates and extensions to our product subscriptions: Personal, Pro, Team, and Business. These updated product subscriptions provide the productivity and collaboration developers rely on with the scale, security, and trusted content businesses require, and do so in a manner sustainable for Docker.

    What you need to know:

    • We’re introducing a new product subscription, Docker Business, for organizations using Docker at scale for application development and require features like secure software supply chain management, single sign-on (SSO), container registry access controls, and more.

    • Our Docker Subscription Service Agreement includes a change to the terms for Docker Desktop:

      4.2 Specific License Limitations – Docker Desktop.

      (a) The Docker Desktop component of the Service at the level of the Personal Offering (as described on the Pricing Page) is further restricted to: (i) your “Personal Use”, (ii) your “Educational Use”, (iii) your use for a non-commercial open source project, and (iv) your use in a “Small Business Environment”.

      (b) For purposes of this Section 4.2: (i) “Personal Use” is the use by an individual developer for personal use to develop free or paid applications, (ii) “Educational Use” is the use by members of an educational organization in a classroom learning environment for academic or research purposes or contribution to an open source project and (iii) a “Small Business Environment” is a commercial undertaking with fewer than 250 employees and less than US $10,000,000 (or equivalent local currency) in annual revenue.

      -- Docker Subscription Service Agreement | Docker

      • Docker Desktop remains free for small businesses (fewer than 250 employees AND less than $10 million in annual revenue), personal use, education, and non-commercial open source projects.
      • It requires a paid subscription (Pro, Team or Business), starting at $5 per user per month, for professional use in larger businesses. You may directly purchase here, or share this post and our solution brief with your manager.
      • While the effective date of these terms is August 31, 2021, there is a GRACE PERIOD until January 31, 2022 for those that require a paid subscription to use Docker Desktop.
    • Docker Pro, Docker Team, and Docker Business subscriptions include commercial use of Docker Desktop.

    • The existing Docker Free subscription has been renamed Docker Personal.

    • No changes to Docker Engine or any upstream open source Docker or Moby project.

    • Check out our FAQ or more information.

    Docker Personal = Free

    • The new Docker Personal subscription replaces the Docker Free subscription. With its focus on open source communities, individual developers, education, and small businesses – which together account for more than half of Docker users – Docker Personal is free for these communities and continues to allow free use of all its components – including Docker CLI, Docker Compose, Docker Build/BuildKit, Docker Engine, Docker Desktop, Docker Hub, Docker Official Images, and more.

    Docker Business = Management and security at scale

    • The new Docker Business subscription enables ORGANIZATION-WIDE MANAGEMENT and SECURITY for businesses that use Docker for software development at scale. With an easy-to-use SaaS-based management plane, IT leaders can now efficiently observe and manage all their Docker development environments and accelerate their secure software supply chain initiatives.

    • In addition to all the capabilities available in the Docker Pro and Docker Team subscriptions, Docker Business adds the ability to control what container images developers can access from Docker Hub, ensuring teams are BUILDING SECURELY FROM THE START by using only trusted content.

      And shortly, Docker Business will provide SAML SSO, the ability to control what registries developers can access, and the ability to remotely manage Docker Desktop instances.

    • More generally, the objective of the new Docker Business subscription is to help large businesses address the following challenges across their development organizations:

      • Gain visibility and control over content

        Which container registries are my developers pulling container images from? What images are they running locally on their laptops? What versions are they running? What security vulnerabilities do those container images have? How can I help my developers protect the organization?

      • Manage local resources and access to external services

        How can I ensure my developers’ local Docker environments are safe? How do I make sure Docker is effectively sharing resources?? with other local tools? How can I manage the networks?? accessible to Docker?

      • Manage Docker development environments at scale

        Many organizations have 100s and 1000s of developers using Docker and need a centralized point of control for developer onboarding/off-boarding with SSO, authentication and authorization, observability of behavior and content, and configuring the above controls.

      The Docker Business subscription launches today at a price of $21 per user per month billed annually. And there’s more on the way – check-out our public roadmap for details.

    Docker Desktop = New subscription terms

    • At Docker we remain committed to continuing to provide an easy-to-use, free experience for individual developers, open source projects, education, and small businesses. In fact, altogether these communities represent more than half of all Docker usage.

      Docker Personal and all its components – including Docker CLI, Docker Compose, Kubernetes, Docker Desktop, Docker Build/BuildKit, Docker Hub, Docker Official Images, and more – remain free for these communities.

    • Specifically, small businesses (fewer than 250 employees AND less than $10 million in revenue) may continue to use Docker Desktop with Docker Personal for free. The use of Docker Desktop in large businesses, however, requires a Pro, Team, or Business paid subscription, starting at $5 per user per month.

    • With Docker Desktop managing all the complexities of integrating, configuring, and maintaining Docker Engine and Kubernetes in Windows and Mac desktop environments – filesystems, VMs, networking, and more – developers can spend more of their time building apps, less on FUSSING WITH INFRASTRUCTURE.

      And with a paid subscription, businesses get additional value in Docker Desktop, including capabilities for managing secure software supply chains, centralizing policy visibility and controls, and managing users and access.

    • The updated terms for Docker Desktop reflect our need to scale our business sustainably and enable us to continue shipping new value in all Docker subscriptions. These new terms take effect August 31, 2021, and there is a grace period until January 31, 2022 for those who require a paid subscription to use Docker Desktop. (Note that licensing for Docker Engine and the upstream Docker and Moby open source projects is not changing.)

    Considering an Alternative to Docker Desktop?

    • Read this blog recapping Docker Captain Bret Fisher‘s video where he reminded his audience of the many things — some of them COMPLEX AND SUBTLE — that Docker Desktop does that make it such a VALUABLE developer tool.
  • Docker Pricing & Monthly Plan Details | Docker

    Pro $5/month, Billed annually for $60.

    • Includes pro tools for individual developers who want to accelerate their productivity.

      Everything in Personal plus:

      • Docker Desktop
      • Unlimited private repositories
      • 5,000 image pulls per day
      • 5 concurrent builds
      • 300 Hub vulnerability scans
      • 5 scoped access tokens

    Team $7/user/month, Start with minimum 5 users for $25, Billed annually starting at $300.

    • Ideal for teams and includes capabilities for collaboration, productivity and security.

      Everything in Pro, plus:

      • Docker Desktop
      • Unlimited teams
      • 15 concurrent builds
      • Unlimited image scans
      • Unlimited scoped tokens
      • Role-based access control
      • Audit logs

      其中 "Start with minimum 5 users for $25, Billed annually starting at $300." 指的是前 5 位 $5/user/month,其他的一樣算 $7/user/month。

    Business, $21/user/month

    • Ideal for medium and large businesses who need CENTRALIZED MANAGEMENT and advanced security capabilities.

      Everything in Team, plus:

      • Docker Desktop
      • Centralized management
      • Image Access Management
      • SAML SSO (coming soon)
      • Purchase via invoice
      • Volume Pricing Available
  • Docker Pricing & Monthly Plan Details | Docker

    My company made just over $10 million last financial year, but we don't expect to do the same this year. Do I need a Docker subscription?

    • Yes. Companies with over 250 employees OR $10 million in annual revenue during their last fiscal year need a paid Docker subscription for all of their developers.

    My company has 50 employees, but is a subsidiary of a company with 1000 employees. Do I need to pay?

    • Yes. As part of a larger company you will need a paid Docker Pro, Team, or Business tier subscription.

Docker 支援 Windows app??

  • 如果多個 container 是共用 OS kernel,那麼內含 Linux app 的 container 不能執行在 Windows host 上,反之亦然?

參考資料:

Hello, World!

$ docker run hello-world

Hello from Docker!
...
$ docker run hello-world

Hello from Docker!
...

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
479d4f07e2fb        hello-world         "/hello"            27 seconds ago      Exited (0) 30 seconds ago                       romantic_galileo
15f9d4284ced        hello-world         "/hello"            29 seconds ago      Exited (0) 31 seconds ago                       hopeful_poincare

原來每做一次 docker run,都產生一個 container。如何重複看到訊息,但只建立一個 container? 用 --name 給個名字:(不要被 docker run 中的 "run" 給騙了)

$ docker run --name hello hello-world

Hello from Docker!
...

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
051fcb601eca        hello-world         "/hello"            29 seconds ago      Exited (0) 32 seconds ago                       hello

如何再看到一次訊息呢?

$ docker run --name hello hello-world # 這行不通,因為 `hello` 這名字已經有 container 使用
$ docker start hello # 什麼事都沒發生?
hello
$ docker start -a hello # 加上 `--attach, -a` 又可以看得到了

Hello from Docker!
...

原來 run 會啟動 container 並自動 attach,但 start 預設是 detached,所以 docker start hello 有執行但看不到輸出。

$ docker help start | grep attach
  -a, --attach               Attach STDOUT/STDERR and forward signals

docker rundocker start 時,預設會執行 Dockerfile 中的 CMD

FROM scratch
COPY hello /
CMD ["/hello"]

執行完就結束了,呼應 docker ps -a 顯示的 "Exited" status。

參考資料:

新手上路 ?? {: #getting-started }

  • 跟著 Getting Started with Docker 做一次,對所有的 term 有整體的瞭解。

    • 似乎可以從 docker run hello-world 開始?
    • 搞清楚 Docker for Mac、Docker Toolbox、Docker Machine、Docker Engine 的不同、關係...
  • Get Started, Part 1: Orientation and setup | Docker Documentation

    Docker concepts

    • Docker is a platform for developers and sysadmins to develop, deploy, and run applications with containers. The use of Linux containers to deploy applications is called CONTAINERIZATION.

      Containers are not new, but their use for easily DEPLOYING APPLICATIONS is.

    • Containerization is increasingly popular because containers are:

      • Flexible: Even the most complex applications can be containerized.
      • Lightweight: Containers LEVERAGE AND SHARE THE HOST KERNEL.
      • Interchangeable: You can deploy updates and upgrades on-the-fly. ??
      • Portable: You can build locally, deploy to the cloud, and run anywhere.
      • Scalable: You can increase and automatically distribute CONTAINER REPLICAS.
      • Stackable: You can STACK SERVICES VERTICALLY and on-the-fly. ??
    • Images and containers

      • A CONTAINER IS LAUNCHED BY RUNNING AN IMAGE. An image is an EXECUTABLE PACKAGE that includes everything needed to run an application--the code, a runtime, libraries, environment variables, and configuration files.

        通常 configuration 會從外面掛進去。

      • A container is a RUNTIME INSTANCE OF AN IMAGE--what the image becomes in memory when executed (that is, an image with state, or a user process). You can see a list of your running containers with the command, docker ps, just as you would in Linux.

    • Containers and virtual machines

      • A container runs NATIVELY on Linux and SHARES THE KERNEL OF THE HOST MACHINE with other containers. It runs a discrete process, taking no more memory than any other executable, making it lightweight.

        不用 docker ps 的話,用 ps 看得到 container 對應的 process 嗎 ??

    • By contrast, a virtual machine (VM) runs a FULL-BLOWN “guest” operating system with VIRTUAL ACCESS TO HOST RESOURCES THROUGH A HYPERVISOR. In general, VMs provide an environment with more resources than most applications need.

      每個 application 都用個別 VM 佈署的話,會多一層 Guest OS,資源運用上比較沒效率;若多個 application 共用一個 VM,環境會混在一起也不可能。

    Prepare your Docker environment

    • Install a maintained version of Docker Community Edition (CE) or Enterprise Edition (EE) on a supported platform.

    • For full Kubernetes Integration

      • Kubernetes on Docker Desktop for Mac is available in 17.12 Edge (mac45) or 17.12 Stable (mac46) and higher.
      • Kubernetes on Docker Desktop for Windows is available in 18.02 Edge (win50) and higher edge channels only.

      Docker 不是自己有 Swarm,為什麼也會推 Kubernetes ??

    Test Docker version

    • Run docker --version and ensure that you have a supported version of Docker:

      $ docker --version
      Docker version 17.12.0-ce, build c97c6d6
      
    • Run docker info (or docker version without --) to view even more details about your Docker installation:

      $ docker info
      Containers: 0
       Running: 0
       Paused: 0
       Stopped: 0
      Images: 0
      Server Version: 17.12.0-ce
      Storage Driver: overlay2
      ...
      
    • To avoid permission errors (and the use of sudo), add your user to the docker group. Read more.

    Test Docker installation

    • Test that your installation works by running the simple Docker image, hello-world:

      $ docker run hello-world
      Unable to find image 'hello-world:latest' locally
      latest: Pulling from library/hello-world
      ca4f61b1923c: Pull complete
      Digest: sha256:ca0eeb6fb05351dfc8759c20733c91def84cb8007aa89a5bf606bc8b315b9fc7
      Status: Downloaded newer image for hello-world:latest
      
      Hello from Docker!
      This message shows that your installation appears to be working correctly.
      ...
      
    • List the hello-world image that was downloaded to your machine:

      docker image ls
      
    • List the hello-world container (spawned by the image) which exits after displaying its message. If it were STILL RUNNING, you would not need the --all option:

      $ docker container ls --all
      CONTAINER ID     IMAGE           COMMAND      CREATED            STATUS
      54f4984ed6a8     hello-world     "/hello"     20 seconds ago     Exited (0) 19 seconds ago
      

    Conclusion of part one

    • Containerization makes CI/CD seamless. For example:

      • applications have NO SYSTEM DEPENDENCIES
      • updates can be pushed to any part of a distributed application ??
      • resource density can be optimized.
    • With Docker, scaling your application is a matter of spinning up new executables, not running heavy VM hosts.

  • Get Started, Part 2: Containers | Docker Documentation #ril

    Introduction

    • It’s time to begin building an app the Docker way. We start at the bottom of the hierarchy of such app, a container, which this page covers. Above this level is a SERVICE, which defines how containers behave in production, covered in Part 3. Finally, at the top level is the STACK, defining the INTERACTIONS OF ALL THE SERVICES, covered in Part 5.

      • Stack
      • Services
      • Container (you are here)

    Your new development environment

    • In the past, if you were to start writing a Python app, your first order of business was to install a Python runtime onto your machine. But, that creates a situation where the environment on your machine needs to be perfect for your app to run as expected, and also needs to MATCH YOUR PRODUCTION ENVIRONMENT.
    • With Docker, you can just grab a portable Python runtime as an image, no installation necessary. Then, your build can include the base Python image right alongside your app code, ensuring that your app, its dependencies, and the runtime, ALL TRAVEL TOGETHER.
    • These portable images are defined by something called a Dockerfile.

    Define a container with Dockerfile

    • Dockerfile defines what goes on in the environment inside your container. Access to resources like networking interfaces and disk drives is VIRTUALIZED INSIDE THIS ENVIRONMENT, which is isolated from the rest of your system, so you need to MAP ports to the outside world, and BE SPECIFIC about what files you want to “COPY IN” to that environment.

      However, after doing that, you can expect that the build of your app defined in this Dockerfile behaves exactly the same wherever it runs.

    • Create an empty directory on your local machine. Change directories (cd) into the new directory, create a file called Dockerfile, copy-and-paste the following content into that file, and save it. Take note of the comments that explain each statement in your new Dockerfile.

      # Use an official Python runtime as a parent image
      FROM python:2.7-slim
      
      # Set the working directory to /app
      WORKDIR /app
      
      # Copy the current directory contents into the container at /app
      COPY . /app
      
      # Install any needed packages specified in requirements.txt
      RUN pip install --trusted-host pypi.python.org -r requirements.txt
      
      # Make port 80 available to the world outside this container
      EXPOSE 80
      
      # Define environment variable
      ENV NAME World
      
      # Run app.py when the container launches
      CMD ["python", "app.py"]
      
    • This Dockerfile refers to a couple of files we haven’t created yet, namely app.py and requirements.txt. Let’s create those next.

    The app itself

    • Create two more files, requirements.txt and app.py, and put them in the same folder with the Dockerfile. This completes our app, which as you can see is quite simple. When the above Dockerfile is built into an image, app.py and requirements.txt is present because of that Dockerfile’s COPY command, and the output from app.py is accessible over HTTP thanks to the EXPOSE command.

      requirements.txt

      Flask
      Redis
      

      app.py

      from flask import Flask
      from redis import Redis, RedisError
      import os
      import socket
      
      # Connect to Redis
      redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
      
      app = Flask(__name__)
      
      @app.route("/")
      def hello():
          try:
              visits = redis.incr("counter")
          except RedisError:
              visits = "<i>cannot connect to Redis, counter disabled</i>"
      
          html = "<h3>Hello {name}!</h3>" \
                 "<b>Hostname:</b> {hostname}<br/>" \
                 "<b>Visits:</b> {visits}"
          return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)
      
      if __name__ == "__main__":
          app.run(host='0.0.0.0', port=80)
      

Now we see that pip install -r requirements.txt installs the Flask and Redis libraries for Python, and the app prints the environment variable NAME, as well as the output of a call to socket.gethostname(). Finally, because Redis isn’t running (as we’ve only installed the Python library, and not Redis itself), we should expect that the attempt to use it here fails and produces the error message.

Note: Accessing the name of the host when inside a container retrieves the container ID, which is like the process ID for a running executable.

That’s it! You don’t need Python or anything in requirements.txt on your system, nor does building or running this image install them on your system. It doesn’t seem like you’ve really set up an environment with Python and Flask, but you have.

Architecture -- Engine, Daemon, Client ??

Docker Daemon ??

Container ??

  • Container 把 software 用到的東西都打包進去,但不像 VM,這裡面不含 OS,只有 code、libraries、settings 等,不只是 isolated/self-contained 且更為輕量,而且跟最後被佈署到哪無關;這個 container 可能只是整個 application 的一部份 (app component)。

參考資料:

Container 是 stateless??

Container 停止後狀態會不見??

Restart Policy ??

One process per container 是個迷思??

  • 正確的說法是 "One concern per container",而 "Once process per container" 的說法則有點偏頗。

參考資料:

Attached/detached? interactive? TTY??

  • docker start 預設是 detached mode,而 docker run 預設是 attached mode;剛好呼應了 docker start 提供了 --attach 參數,而 docker run 則提供 --detach

參考資料:

docker run 如何執行多個指令??

什麼是 service??

Container 並不是完整的 OS??

Docker 可以執行在 VM 裡?

Runtime Constraints??

Ubuntu 的 Docker image 能夠取代 Ubuntu VM 嗎??

如何為 container 重新命名?

docker run 若忘了加 --name 自訂名稱,事後還是可以用 docker rename 更名:

docker rename CONTAINER NEW_NAME

參考資料:

root, USER, --user ??

如何查詢 image/container 暫用的磁碟空間?

$ sudo docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              214                 34                  12.78GB             12.24GB (95%)
Containers          162                 0                   11.45GB             11.45GB (100%)
Local Volumes       0                   0                   0B                  0B

$ sudo docker system prune --all
WARNING! This will remove:
    - all stopped containers
    - all volumes not used by at least one container
    - all networks not used by at least one container
    - all images without at least one container associated to them
Are you sure you want to continue? [y/N] y

...
Total reclaimed space: xx.xxGB

參考資料:

如何建立/暫停/繼續/停止 container??

  • 在 image 的基礎上執行 command,就產生了一個 (running) container,而這個 command 可以從 docker rundocker create 的參數提供 ([COMMAND] [ARG...]),或者 image 通常會提供預設值 (Dockerfile 裡的 CMD),這呼應了 "run image as container" 的說法,以及 docker ps 會看到 Exited (0) 之類的 status。

  • 由於 container 跟 command 的執行脫不了關係,所以 command 在 docker rundocker create 就決定了,所以 docker start 沒有 [COMMAND] [ARG...] 的用法。只是 docker create 建立 container 後沒有馬上執行,可以把 docker run 視為 docker create + docker start --attach 的組合。

  • CMD - Dockerfile reference | Docker Documentation https://docs.docker.com/engine/reference/builder/#cmd CMD 的用法有 3 種 - CMD ["executable","param1","param2"] (exec form)、CMD ["param1","param2"] (做為 ENTRYPOINT 的預設參數、CMD command param1 param2 (shell form),都跟要 "如何執行" 的預設值有關,也就是說 CMD 在 build time 不會執行,只是描述 "intended command for the image",可以從 command line 覆寫,也就是 docker rundocker create 後面 [COMMAND] [ARG...] 的部份。

  • docker create | Docker Documentation https://docs.docker.com/engine/reference/commandline/create/ docker create 類似於 docker run --detach,準備好執行特定的 command,但

  • docker run 可以解讀為 "run image as container"。

  • docker start (Start one or more stopped containers) 跟 docker run (Run a command in a new container) 是什麼關係? 為什麼 docker start 沒有 --publish/-p 這類參數,感覺 run 就要決定了,之後的 start 不能再改變?

  • docker exec (Run a command in a running container) 跟 docker run (Run a command in a new container) 有什麼不同?

docker run/start/exec 與 Dockerfile 裡 CMD、ENTRYPOINT 的關係??

  • ENTRYPOINT - Dockerfile reference | Docker Documentation ENTRYPOINT ["executable", "param1", "param2"] 是其中一種 exec form 的寫法,在 docker run IMAGE 提供的參數都會 "附加" 到 ENTRYPOINT 之後,同時也覆寫了 CMD 的 default arguments (ENTRYPOINT 裡提供的 params 固定會有,跟 CMD 無關);但 ENTRYPOINT 也可以用 docker run --entrypoint 覆寫。
  • CMD - Dockerfile reference | Docker Documentation 提到 CMD 若要做為 ENTRYPOINT 的 default arguments,那麼 ENTRYPOINTCMD 都要用 JSON array format 寫 #ril
  • Exec form ENTRYPOINT example - Dockerfile reference | Docker Documentationdocker exec -it test ps aux 的例子看來,docker execENTRYPOINTCMD 都無關,而且對象是一個 running container。
  • 若要包裝 image 給別人執行,善用 ENTRYPOINT 提供預設的參數 (例如 ENTRYPOINT ["uwsgi", "--ini", "uwsgi.ini"]),搭配 CMD 提供可以從 command line 自訂的範例,這樣佈署的人就可以從 docker run your_image 後面直接提供參數,覆寫 ENTRYPOINT 預設的參數。

如何查詢有哪些 container? 刪除用到不到 container?

  • docker start - Start one or more stopped containers,應該是對應 docker stop - Stop one or more running containers。但
  • docker ps | Docker Documentation https://docs.docker.com/engine/reference/commandline/ps/ docker ps 預設會列出執行中 (running) 的 container,加上 -a (--all) 會列出所有 container,包含 stopped

docker build

  • Dockerfile reference | Docker Documentation #ril
  • docker build | Docker Documentation #ril
    • 根據 Dockerfile 與 build context 裝配一個 image,所謂 context 是 "set of files at a specified location",可以是 local path 或 (Git) URL。
    • Image 是由 Docker daemon 來 build,一開始會蒐集 context 裡的檔案 (先根據 .dockerignore 排除一些檔案) 進 daemon -- recursively (含 subdirectories 或 submodules),那會成為 Dockerfile 裡參照檔案的來源。
    • 習慣上會將 Dockerfile 放 root of the context,也可以用 -f, --file 指定。
    • 可以用 -t, --tag 為最後的 image 加上 repository 及 tag。
  • 觀察 docker build 的輸出,一開始會提示 "Sending build context to Docker daemon XXX MB"

Tag, Image Name ??

  • Tag an image (-t) - docker build | Docker Documentation

    • --tag, -t 的說明是 "Name and optionally a tag in the ‘name:tag’ format",在 docker help build 看到的則是 "-t, --tag list Name and optionally a tag in the 'name:tag' format" 所以 --tag 可以是 name[:tag],對照 docker image ls 輸出的欄位,name 就是 repository name;而 list 是指可以使用多次 (給多個不同的 tag)
    • 從 Docker Hub 的操作介面看來,一個 repository 就是一個 image,但可以有許多 tag;例如 python 的 repository 下有多個 tag,不同的 tag 除了版號不同,也可以區分不同的版本 (variation),例如 2.7.15-alpine2.7.15-slim
    • 為 resulting image 加上 tag,以 docker build -t vieux/apache:2.0 . 為例,vieux/apache 是 repository name (沒有 repository URL,但 vieux/ 可以視為 namespace),2.0 才是 tag。使用多個 -t 就可以為 image 加上多個 tags,例如 docker build -t whenry/fedora-jboss:latest -t whenry/fedora-jboss:v2.1 . (顯然 name 是必要的)。
  • docker tag | Docker Documentation 建立一個 tag TARGET_IMAGE 參照 SOURCE_IMAGE?? #ril

    • docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG] 建立一個 tag TARGET_IMAGE 指向 SOURCE_IMAGE?
    • 首次出現 "image name" 與 "tag name" 的說法!! 但由 "You can group your images together using names and tags, and then upload them ..." 這句看來,單純提到 name 時,指的則是 image name,相對於 tag 而言。
    • Image name 由 / (slash) 分隔開來的 name components 構成,前面也可以有 registry hostname (可以帶 port,但不能有底線);所以 image name 的格式為 [registry_hostname[:port]]name_components,其中 registry_hostname 預設是 registry-1.docker.io (central Docker registry),而 name_components 就 Docker Hub 而言,就是 namespace/repository,例如 username/my-project,完整的表示法像是 myregistryhost:5000/fedora/httpd:version1.0
    • 其中 name_components 只能由數字、小寫字母及一些 separator 組成,其中 separator 可以是 . (period)、1 ~ 2 個 _ (underscore)、1 或多個 - (dash),但開頭不能是 separator。而 tag name 則可以由大小寫字母、數字、底線、. (period) 及 - (dash) 組成 (也就是不能有 :/ 等),最長 128 個字元。
    • 從幾個 "Tag an image referenced by ..." 的例子看來,SOURCE_IMAGE[:TAG] 的表示法是有問題的,因為 name[:tag] 的表示法也是為了找到特定的 soruce image (tag 預設為 latest),給 image ID 是最明確的。
  • Usage - Dockerfile reference | Docker Documentation 提到 "You can specify a repository and tag at which to save the new image if the build succeeds" 及 "To tag the image into multiple repositories after the build" 的說法,原來 -t 不只是 tag,還包含了 repository,例如 -t shykes/myapp:1.0.2

  • Build 出了兩個 image -- proj1:latestproj2:latest,執行 docker tag proj1:latest proj2:latest 後,proj2:latest 也指向 proj1:latest 相同的 image ID,而原來 proj2:latest 指向的 image ID 在 docker image ls 裡則呈現 <none>:<none>,由此可見 name[:tag] 只是 image ID 的 alias。

  • What are Docker : images? — Project Atomic (2015-07-16) #ril

  • Docker Explained: Using Dockerfiles to Automate Building of Images | DigitalOceandocker build -t IMAGE_NAME . 來建立 image,但 -t, --tag list 的說明是 Name and optionally a tag in the 'name:tag' format ?

  • library/ubuntu - Docker Hub https://hub.docker.com/_/ubuntu/ 看到 Supported tags and respective Dockerfile links 及 The ubuntu:latest tag points to the "latest LTS" 的說法。

Makefile, GitLab CI ??

# Parameters
VERSION ?= $(shell cat VERSION)

# GitLab CI/CD Variables (for testing)
CI_REGISTRY ?= gitlab.example.com:4567
CI_PROJECT_PATH ?= ateam/awesome-project
CI_COMMIT_SHA ?= 0123456789abcdef0123456789abcdef01234567

# Internal Variables
ifdef CI
	image = $(CI_REGISTRY)/$(CI_PROJECT_PATH)/commit:$(CI_COMMIT_SHA) <-- 送往下一層,方便定期清理
else
	image = $(CI_PROJECT_PATH)
endif

build:
	docker build -t $(image) .
ifdef CI
	$(login-ci-registry)
	docker push $(image) <-- CI 下自動往 registry 送,其他 job 才拿得到
endif

ifdef CI_REGISTRY_USER
define login-ci-registry
	@docker login -u '$(CI_REGISTRY_USER)' -p '$(CI_REGISTRY_PASSWORD)' $(CI_REGISTRY)
endef
else
define login-ci-registry
	@docker login $(CI_REGISTRY)
endef
endif

ifdef CI_COMMIT_TAG
release: image_release = $(CI_REGISTRY)/$(CI_PROJECT_PATH):$(CI_COMMIT_TAG)
release:
ifneq ($(CI_COMMIT_TAG),$(VERSION)) <-- 自動檢查 VERSION file 與觸發的 Git tag 是否一致
	$(error CI_COMMIT_TAG ($(CI_COMMIT_TAG)) != VERSION ($(VERSION)))
endif
	$(login-ci-registry)
	docker pull $(image)
	docker tag $(image) $(image_release) <-- 直接把 commit/<sha> 標上版號,送往它該去的地方
	docker push $(image_release)
endif
image: docker:stable

stages:
  - build
  - deploy

build_image:
  stage: build
  tags:
    - dind
  only:
    - branches
  script:
    - apk add --no-cache make
    - make build

release_image:
  stage: deploy
  tags:
    - dind
  except:
    - branches
  only:
    - /^\d+\.\d+\.\d+$/
  script:
    - apk add --no-cache make
    - make release

Registry ??

.dockerignore ??

要同時維護 .gitignore.dockerignore 似乎不太容易? 因為兩者不完全重疊,例如 .git/ 不在 .gitignore 裡,但卻要從 .dockerignore 裡排除。

按照 Usage - Dockerfile reference | Docker Documentation 的說法:

In most cases, it’s best to start with an empty directory as context and keep your Dockerfile in that directory. Add only the files needed for building the Dockerfile.

可以考慮做 whitelisting - 先用 * 排除,再明確把要放進 image 的檔案用 ! 加回來。例如:

*
!Dockerfile
!dist/

在 build image 前,可以用 git clean -xdf 確保 source 是可以預期的。

參考資料:

如何打造自己的 image??

如何管理 image??

拿到一個 image 後,如何知道它是怎麼被建構出來的??

Docker Hub?

如何建立自己的 Container Registry (Docker Hub)??

多個 Dockerfile??

如何將 Docker 應用在平時的開發??

如何將現有的 app 搬到 container 裡??

  • Docker - Build, Ship, and Run Any App, Anywhere https://www.docker.com/ WORKS WITH ANY STACK 提到 "Deploy both microservices and traditional apps anywhere without costly rewrites." 不用重寫,但要做哪些調整? 可以把所有 component 都裝在同一個 container 裡?

如何在 Pi 上執行 Docker??

其他

其他:

  • Learn Docker - Docker https://docs.docker.com/learn/ #ril

  • Get started with Docker - Docker https://docs.docker.com/engine/getstarted/ #ril

  • Learn Docker in 12 Minutes 🐳 - YouTube https://www.youtube.com/watch?v=YFl2mCHdv24 #ril

  • 感覺一個 container 就是一個 process 執行在裡面??

    • DockerfileCMD 的用法看來,一個 container 似乎可以想成一個 application??
    • 假設 app 要連資料庫怎麼辦? 資料庫要運作在另一個 container 裡?? 中間要怎麼連結??
    • docker run 的行為最難懂,什麼是 attach/detach?? 為什麼 container 一跑完就會 exited??
  • Docker Hub 跟 Docker Cloud 有什麼差別??

    • 這裡 "As an alternative to using Docker Hub to store your public or private images or Docker Trusted Registry," 的說法,Docker Hub 也支援 private image ...
  • Docker 有好多元件組成,一開始好難搞懂其間的關係?? Docker Engine、Docker Compose、Docker Machine ... 另外還有個 Docker Daemon

  • docker run hello-world 建議試試 docker run -it ubuntu bash

    • 其中 -i (--interactive) 的作用是 "Keep STDIN open even if not attached",而 -t (--tty) 的作用則是 "Allocate a pseudo-TTY"。
    • 最後的 bash 是傳給 application 的指令?? 但 Dockerfile 裡已經寫 CMD ["/bin/bash"]??

如何在 Docker 裡包 image??

$ docker run --rm --tty \
  --volume $(PWD):/workspace \
  --workdir /workspace \
  docker:dind docker info
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

加上 /var/run/docker.sock:/var/run/docker.sock 的對應即可:

$ docker run --rm --tty \
  --volume $(PWD):/workspace \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  --workdir /workspace \
  docker:dind docker info
...

參考資料:

Timezone ??

  • docker run --env TZ=XXX 的做法似乎只能作用在該 process,比較全面的做法應該是改寫 /etc/localtime?

參考資料:

The input device is not a TTY

  • 在 GitLab CI 上執行 docker run -it 會直接噴 The input device is not a TTY 的錯誤,不過只用 -t, --tty 時就沒這個問題,而且在本地開發時,也可以按 Ctrl-C 中斷 container (而且輸出也會有顏色),那 -i 什麼時候要加?

參考資料:

環境變數 {: #environment-variables }

  • docker run | Docker Documentation #ril

    • --env , -e -- Set environment variables
    • --env-file -- Read in a file of environment variables

    Set environment variables (-e, --env, --env-file)

    $ docker run -e MYVAR1 --env MYVAR2=foo --env-file ./env.list ubuntu bash
    
    • Use the -e, --env, and --env-file flags to set simple (non-array) environment variables in the container you’re running, or overwrite variables that are defined in the Dockerfile of the image you’re running.

    • You can define the variable and its value when running the container:

      $ docker run --env VAR1=value1 --env VAR2=value2 ubuntu env | grep VAR
      VAR1=value1
      VAR2=value2
      
    • You can also use variables that you’ve EXPORTED to your local environment:

      export VAR1=value1
      export VAR2=value2
      
      $ docker run --env VAR1 --env VAR2 ubuntu env | grep VAR
      VAR1=value1
      VAR2=value2
      
    • When running the command, the Docker CLI client checks the value the variable has in your local environment and PASSES IT TO THE CONTAINER. If no = is provided and that variable is not exported in your local environment, the variable won’t be set in the container.

    • You can also load the environment variables from a file. This file should use the syntax <variable>=value (which sets the variable to the given value) or <variable> (which TAKES THE VALUE FROM THE LOCAL ENVIRONMENT), and # for comments.

Testing ??

安裝設置 {: #setup }

macOS

  • OS 要求 macOS El Capitan 10.11 以上,硬體要是 2012 年後,用 sysctl kern.hv_support 檢查 (要是 kern.hv_support: 1),要求 4GB RAM。
  • 下載 Docker.dmg 安裝。
  • 視情況取消 Preferences > Daemon > Experimental features

參考資料:

  • Install Docker Desktop for Mac | Docker Documentation #ril

  • Docker for Mac doesn't listen on 2375 · Issue #770 · docker/for-mac

    • Docker for Mac should listen on 2375, providing an HTTP API server.

    • samoht (contributor): For security reasons, we choose to not expose that port directly. However, as described in our FAQ you can run a SOCAT CONTAINER to redirect the Docker API exposed on the unix domain socket in Linux to the port of your choice on your OSX host:

      $ docker run -d -v /var/run/docker.sock:/var/run/docker.sock -p 127.0.0.1:1234:1234 \
                   bobrik/socat TCP-LISTEN:1234,fork UNIX-CONNECT:/var/run/docker.sock
      

      and then:

      export DOCKER_HOST=tcp://localhost:1234
      

      採慣用的 2375 port 更直覺。

Ubuntu

$ sudo apt-get update
$ # 讓 apt 可以透過 HTTPS 用 repository?
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
$ # 增加 Docker 官方的 GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ # 加入 stable repository (這裡以 amd64 為例)
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# 安裝 docker-ce 套件,可以用 docker-ce=VERSION 指定版本
$ apt-get update
$ sudo apt-get install docker-ce

# 最後執行 hello-world image 試看看
$ docker run --rm hello-world

執行 dockersudo 的問題,可以把使用者加到 docker group 即可:

$ sudo usermod -aG docker USER
$ newgrp docker # 刷新 login session 的群組,不用重新登入

參考資料:

Mac 上的 Docker 要用到 VirtualBox?

  • 早期的 Docker Toolbox 確實採用 VirtualBox,但後來的 Docker for Mac 已改用新的 virtualization system - HyperKit - 基於 macOS 10.10 才有的 Hypervisor.framework

參考資料:

Raspberry Pi ??

參考資料 {: #reference }

社群:

工具:

更多:

手冊: