{"id":259,"date":"2022-12-24T08:58:24","date_gmt":"2022-12-24T06:58:24","guid":{"rendered":"https:\/\/amsd.go.ro\/wordpress\/?p=259"},"modified":"2022-12-24T08:58:24","modified_gmt":"2022-12-24T06:58:24","slug":"how-to-install-and-use-docker-compose-on-centos","status":"publish","type":"post","link":"https:\/\/amsd.go.ro\/wordpress\/?p=259","title":{"rendered":"How To Install and Use Docker Compose on CentOS"},"content":{"rendered":"\n<p><a href=\"https:\/\/docs.docker.com\/\">Docker<\/a> is a great tool for automating the deployment of Linux applications inside software containers, but to really take full advantage of its potential it\u2019s best if each component of your application runs in its own container. For complex applications with a lot of components, orchestrating all the containers to start up and shut down together (not to mention talk to each other) can quickly become unwieldy.<\/p>\n\n\n\n<p>The Docker community came up with a popular solution called <a href=\"http:\/\/www.fig.sh\/\">Fig<\/a>, which allowed you to use a single YAML file to orchestrate all your Docker containers and configurations. This became so popular that the Docker team decided to make <em>Docker Compose<\/em> based on the Fig source, which is now deprecated. Docker Compose makes it easier for users to orchestrate the processes of Docker containers, including starting up, shutting down, and setting up intra-container linking and volumes.<\/p>\n\n\n\n<p>In this tutorial, you will install the latest version of Docker Compose to help you manage multi-container applications, and will explore the basic commands of the software.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"docker-and-docker-compose-concepts\">Docker and Docker Compose Concepts<\/h2>\n\n\n\n<p>Using Docker Compose requires a combination of a bunch of different Docker concepts in one, so before we get started let\u2019s take a minute to review the various concepts involved. If you\u2019re already familiar with Docker concepts like volumes, links, and port forwarding then you might want to go ahead and skip on to the next section.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"docker-images\">Docker Images<\/h3>\n\n\n\n<p>Each Docker container is a local instance of a Docker image. You can think of a Docker image as a complete Linux installation. Usually a minimal installation contains only the bare minimum of packages needed to run the image. These images use the kernel of the host system, but since they are running inside a Docker container and only see their own file system, it\u2019s perfectly possible to run a distribution like CentOS on an Ubuntu host (or vice-versa).<\/p>\n\n\n\n<p>Most Docker images are distributed via the <a href=\"https:\/\/hub.docker.com\/\">Docker Hub<\/a>, which is maintained by the Docker team. Most popular open source projects have a corresponding image uploaded to the Docker Registry, which you can use to deploy the software. When possible, it\u2019s best to grab \u201cofficial\u201d images, since they are guaranteed by the Docker team to follow Docker best practices.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"communication-between-docker-images\">Communication Between Docker Images<\/h3>\n\n\n\n<p>Docker containers are isolated from the host machine, meaning that by default the host machine has no access to the file system inside the Docker container, nor any means of communicating with it via the network. This can make configuring and working with the image running inside a Docker container difficult.<\/p>\n\n\n\n<p>Docker has three primary ways to work around this. The first and most common is to have Docker specify environment variables that will be set inside the Docker container. The code running inside the Docker container will then check the values of these environment variables on startup and use them to configure itself properly.<\/p>\n\n\n\n<p>Another commonly used method is a Docker data volume. Docker volumes come in two flavors \u2014 internal and shared.<\/p>\n\n\n\n<p>Specifying an internal volume just means that for a folder you specify for a particular Docker container, the data will be persisted when the container is removed. For example, if you wanted to make sure your log files persisted you might specify an internal <code>\/var\/log<\/code> volume.<\/p>\n\n\n\n<p>A shared volume maps a folder inside a Docker container onto a folder on the host machine. This allows you to easily share files between the Docker container and the host machine.<\/p>\n\n\n\n<p>The third way to communicate with a Docker container is via the network. Docker allows communication between different Docker containers via <code>links<\/code>, as well as port forwarding, allowing you to forward ports from inside the Docker container to ports on the host server. For example, you can create a link to allow your WordPress and MariaDB Docker containers to talk to each other and use port-forwarding to expose WordPress to the outside world so that users can connect to it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-1-installing-docker-compose\">Step 1 \u2014 Installing Docker Compose<\/h2>\n\n\n\n<p>In order to get the latest release, take the lead of the <a href=\"https:\/\/docs.docker.com\/compose\/install\/\">Docker docs<\/a> and install Docker Compose from the binary in Docker\u2019s GitHub repository.<\/p>\n\n\n\n<p>Check the <a href=\"https:\/\/github.com\/docker\/compose\/releases\">current release<\/a> and if necessary, update it in the command below:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo curl -L \"https:\/\/github.com\/docker\/compose\/releases\/download\/<mark>1.23.2<\/mark>\/docker-compose-$(uname -s)-$(uname -m)\" -o \/usr\/bin\/docker-compose\n\n<\/code><\/pre>\n\n\n\n<p>Next, set the permissions to make the binary executable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chmod +x \/usr\/bin\/docker-compose\n\n<\/code><\/pre>\n\n\n\n<p>Then, verify that the installation was successful by checking the version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose --version\n\n<\/code><\/pre>\n\n\n\n<p>This will print out the version you installed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Outputdocker-compose version <mark>1.23.2<\/mark>, build 1110ad01\n<\/code><\/pre>\n\n\n\n<p>Now that you have Docker Compose installed, you\u2019re ready to run a \u201cHello World\u201d example.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-2-running-a-container-with-docker-compose\">Step 2 \u2014 Running a Container with Docker Compose<\/h2>\n\n\n\n<p>The public Docker registry, Docker Hub, includes a simple \u201cHello World\u201d image for demonstration and testing. It illustrates the minimal configuration required to run a container using Docker Compose: a YAML file that calls a single image.<\/p>\n\n\n\n<p>First, create a directory for our YAML file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir hello-world\n\n<\/code><\/pre>\n\n\n\n<p>Then change into the directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd hello-world\n\n<\/code><\/pre>\n\n\n\n<p>Now create the YAML file using your favorite text editor. This tutorial will use Vi:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi docker-compose.yml\n\n<\/code><\/pre>\n\n\n\n<p>Enter insert mode, by pressing <code>i<\/code>, then put the following contents into the file: docker-compose.yml<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>my-test:\n  image: hello-world\n<\/code><\/pre>\n\n\n\n<p>The first line will be part of the container name. The second line specifies which image to use to create the container. When you run the command <code>docker-compose up<\/code> it will look for a local image by the name specified, <code>hello-world<\/code>.<\/p>\n\n\n\n<p>With this in place, hit <code>ESC<\/code> to leave insert mode. Enter <code>:x<\/code> then <code>ENTER<\/code> to save and exit the file.<\/p>\n\n\n\n<p>To look manually at images on your system, use the <code>docker images<\/code> command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker images\n\n<\/code><\/pre>\n\n\n\n<p>When there are no local images at all, only the column headings display:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>OutputREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE\n<\/code><\/pre>\n\n\n\n<p>Now, while still in the <code>~\/hello-world<\/code> directory, execute the following command to create the container:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose up\n\n<\/code><\/pre>\n\n\n\n<p>The first time we run the command, if there\u2019s no local image named <code>hello-world<\/code>, Docker Compose will pull it from the Docker Hub public repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>OutputPulling my-test (hello-world:)...\nlatest: Pulling from library\/hello-world\n1b930d010525: Pull complete\n. . .\n<\/code><\/pre>\n\n\n\n<p>After pulling the image, <code>docker-compose<\/code> creates a container, attaches, and runs the <a href=\"https:\/\/github.com\/docker-library\/hello-world\/blob\/85fd7ab65e079b08019032479a3f306964a28f4d\/hello-world\/Dockerfile\">hello<\/a> program, which in turn confirms that the installation appears to be working:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Output. . .\nCreating helloworld_my-test_1...\nAttaching to helloworld_my-test_1\nmy-test_1 | \nmy-test_1 | Hello from Docker.\nmy-test_1 | This message shows that your installation appears to be working correctly.\nmy-test_1 | \n. . .\n<\/code><\/pre>\n\n\n\n<p>It will then print an explanation of what it did:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Output. . .\nmy-test_1  | To generate this message, Docker took the following steps:\nmy-test_1  |  1. The Docker client contacted the Docker daemon.\nmy-test_1  |  2. The Docker daemon pulled the \"hello-world\" image from the Docker Hub.\nmy-test_1  |     (amd64)\nmy-test_1  |  3. The Docker daemon created a new container from that image which runs the\nmy-test_1  |     executable that produces the output you are currently reading.\nmy-test_1  |  4. The Docker daemon streamed that output to the Docker client, which sent it\nmy-test_1  |     to your terminal.\n. . .\n<\/code><\/pre>\n\n\n\n<p>Docker containers only run as long as the command is active, so once <code>hello<\/code> finished running, the container stops. Consequently, when you look at active processes, the column headers will appear, but the <code>hello-world<\/code> container won\u2019t be listed because it\u2019s not running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker ps\n\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>OutputCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES\n<\/code><\/pre>\n\n\n\n<p>Use the <code>-a<\/code> flag to show all containers, not just the active ones:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker ps -a\n\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>OutputCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES\n50a99a0beebd        hello-world         \"\/hello\"            3 minutes ago       Exited (0) 3 minutes ago                       hello-world_my-test_1\n<\/code><\/pre>\n\n\n\n<p>Now that you have tested out running a container, you can move on to exploring some of the basic Docker Compose commands.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-3-learning-docker-compose-commands\">Step 3 \u2014&nbsp;Learning Docker Compose Commands<\/h2>\n\n\n\n<p>To get you started with Docker Compose, this section will go over the general commands that the <code>docker-compose<\/code> tool supports.<\/p>\n\n\n\n<p>The <code>docker-compose<\/code> command works on a per-directory basis. You can have multiple groups of Docker containers running on one machine \u2014 just make one directory for each container and one <code>docker-compose.yml<\/code> file for each directory.<\/p>\n\n\n\n<p>So far you\u2019ve been running <code>docker-compose up<\/code> on your own, from which you can use <code>CTRL-C<\/code> to shut the container down. This allows debug messages to be displayed in the terminal window. This isn\u2019t ideal though; when running in production it is more robust to have <code>docker-compose<\/code> act more like a service. One simple way to do this is to add the <code>-d<\/code> option when you <code>up<\/code> your session:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose up -d\n<\/code><\/pre>\n\n\n\n<p><code>docker-compose<\/code> will now fork to the background.<\/p>\n\n\n\n<p>To show your group of Docker containers (both stopped and currently running), use the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose ps -a\n<\/code><\/pre>\n\n\n\n<p>If a container is stopped, the <code>State<\/code> will be listed as <code>Exited<\/code>, as shown in the following example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Output        Name            Command   State    Ports\n------------------------------------------------\nhello-world_my-test_1   \/hello    Exit 0        \n<\/code><\/pre>\n\n\n\n<p>A running container will show <code>Up<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Output     Name              Command          State        Ports      \n---------------------------------------------------------------\nnginx_nginx_1   nginx -g daemon off;   <mark>Up<\/mark>      443\/tcp, 80\/tcp \n<\/code><\/pre>\n\n\n\n<p>To stop all running Docker containers for an application group, issue the following command in the same directory as the <code>docker-compose.yml<\/code> file that you used to start the Docker group:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose stop\n<\/code><\/pre>\n\n\n\n<p><strong>Note:<\/strong> <code>docker-compose kill<\/code> is also available if you need to shut things down more forcefully.<\/p>\n\n\n\n<p>In some cases, Docker containers will store their old information in an internal volume. If you want to start from scratch you can use the <code>rm<\/code> command to fully delete all the containers that make up your container group:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose rm \n<\/code><\/pre>\n\n\n\n<p>If you try any of these commands from a directory other than the directory that contains a Docker container and <code>.yml<\/code> file, it will return an error:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>OutputERROR:\n        Can't find a suitable configuration file in this directory or any\n        parent. Are you in the right directory?\n\n        Supported filenames: docker-compose.yml, docker-compose.yaml\n<\/code><\/pre>\n\n\n\n<p>This section has covered the basics of how to manipulate containers with Docker Compose. If you needed to gain greater control over your containers, you could access the filesystem of the Docker container and work from a command prompt inside your container, a process that is described in the next section.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"step-4-accessing-the-docker-container-filesystem\">Step 4 \u2014&nbsp;Accessing the Docker Container Filesystem<\/h2>\n\n\n\n<p>In order to work on the command prompt inside a container and access its filesystem, you can use the <code>docker exec<\/code> command.<\/p>\n\n\n\n<p>The \u201cHello World\u201d example exits after it runs, so to test out <code>docker exec<\/code>, start a container that will keep running. For the purposes of this tutorial, use the <a href=\"https:\/\/hub.docker.com\/_\/nginx\/\">Nginx image<\/a> from Docker Hub.<\/p>\n\n\n\n<p>Create a new directory named <code>nginx<\/code> and move into it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir ~\/nginx\ncd ~\/nginx\n\n<\/code><\/pre>\n\n\n\n<p>Next, make a <code>docker-compose.yml<\/code> file in your new directory and open it in a text editor:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi docker-compose.yml\n\n<\/code><\/pre>\n\n\n\n<p>Next, add the following lines to the file: ~\/nginx\/docker-compose.yml<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nginx:\n  image: nginx\n<\/code><\/pre>\n\n\n\n<p>Save the file and exit. Start the Nginx container as a background process with the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose up -d\n\n<\/code><\/pre>\n\n\n\n<p>Docker Compose will download the Nginx image and the container will start in the background.<\/p>\n\n\n\n<p>Now you will need the <code>CONTAINER ID<\/code> for the container. List all of the containers that are running with the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker ps\n\n<\/code><\/pre>\n\n\n\n<p>You will see something similar to the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Output of `docker ps`CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES\nb86b6699714c        nginx               \"nginx -g 'daemon of\u2026\"   20 seconds ago      Up 19 seconds       80\/tcp              nginx_nginx_1\n<\/code><\/pre>\n\n\n\n<p>If you wanted to make a change to the filesystem inside this container, you\u2019d take its ID (in this example <code>b86b6699714c<\/code>) and use <code>docker exec<\/code> to start a shell inside the container:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker exec -it <mark>b86b6699714c<\/mark> \/bin\/bash\n\n<\/code><\/pre>\n\n\n\n<p>The <code>-t<\/code> option opens up a terminal, and the <code>-i<\/code> option makes it interactive. <code>\/bin\/bash<\/code> opens a bash shell to the running container.<\/p>\n\n\n\n<p>You will then see a bash prompt for the container similar to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>root@<mark>b86b6699714c<\/mark>:\/#\n<\/code><\/pre>\n\n\n\n<p>From here, you can work from the command prompt inside your container. Keep in mind, however, that unless you are in a directory that is saved as part of a data volume, your changes will disappear as soon as the container is restarted. Also, remember that most Docker images are created with very minimal Linux installs, so some of the command line utilities and tools you are used to may not be present.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Docker is a great tool for automating the deployment of Linux applications inside software containers, but to really take full advantage of its potential it\u2019s best if each component of your application runs in its own container. For complex applications [&hellip;]<\/p>\n<div class=\"link-more\"><a href=\"https:\/\/amsd.go.ro\/wordpress\/?p=259#more-259\" class=\"more-link\">Continue reading &#10142; <span class=\"screen-reader-text\">How To Install and Use Docker Compose on CentOS<\/span><\/a><\/div>","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-259","post","type-post","status-publish","format-standard","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/259","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=259"}],"version-history":[{"count":1,"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/259\/revisions"}],"predecessor-version":[{"id":260,"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/259\/revisions\/260"}],"wp:attachment":[{"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=259"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=259"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/amsd.go.ro\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=259"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}