Warning: preg_match(): Unknown modifier '-' in /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php on line 783

Warning: preg_match(): Unknown modifier '-' in /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php on line 783

Warning: preg_match(): Unknown modifier '-' in /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php on line 783

Warning: preg_match(): Unknown modifier '-' in /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php on line 783

Warning: preg_match(): Unknown modifier '-' in /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php on line 783

Warning: preg_match(): Unknown modifier '-' in /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php on line 783

Warning: preg_match(): Unknown modifier '-' in /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php on line 783

Warning: preg_match(): Unknown modifier '-' in /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php on line 783

Warning: Cannot modify header information - headers already sent by (output started at /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php:783) in /home/akl1986/public_html/support/wp-includes/rest-api/class-wp-rest-server.php on line 1794

Warning: Cannot modify header information - headers already sent by (output started at /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php:783) in /home/akl1986/public_html/support/wp-includes/rest-api/class-wp-rest-server.php on line 1794

Warning: Cannot modify header information - headers already sent by (output started at /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php:783) in /home/akl1986/public_html/support/wp-includes/rest-api/class-wp-rest-server.php on line 1794

Warning: Cannot modify header information - headers already sent by (output started at /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php:783) in /home/akl1986/public_html/support/wp-includes/rest-api/class-wp-rest-server.php on line 1794

Warning: Cannot modify header information - headers already sent by (output started at /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php:783) in /home/akl1986/public_html/support/wp-includes/rest-api/class-wp-rest-server.php on line 1794

Warning: Cannot modify header information - headers already sent by (output started at /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php:783) in /home/akl1986/public_html/support/wp-includes/rest-api/class-wp-rest-server.php on line 1794

Warning: Cannot modify header information - headers already sent by (output started at /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php:783) in /home/akl1986/public_html/support/wp-includes/rest-api/class-wp-rest-server.php on line 1794

Warning: Cannot modify header information - headers already sent by (output started at /home/akl1986/public_html/support/wp-content/plugins/redux-framework/redux-core/inc/extensions/metaboxes/class-redux-extension-metaboxes.php:783) in /home/akl1986/public_html/support/wp-includes/rest-api/class-wp-rest-server.php on line 1794
{"id":2661,"date":"2019-12-06T23:53:52","date_gmt":"2019-12-06T23:53:52","guid":{"rendered":"https:\/\/support.aklwebhost.com\/?post_type=manual_kb&p=2661"},"modified":"2019-12-06T23:54:05","modified_gmt":"2019-12-06T23:54:05","slug":"on-coreos-setup-your-own-docker-registry","status":"publish","type":"manual_kb","link":"https:\/\/support.aklwebhost.com\/knowledgebase\/on-coreos-setup-your-own-docker-registry\/","title":{"rendered":"On CoreOS, Setup Your Own Docker Registry"},"content":{"rendered":"

We all know and love Docker, a platform to create, manage and distribute application containers across multiple machines. Docker Inc. provides a service to host open source containers to be downloaded (or pulled) like a git repository known as the “Docker Registry.” Think of it like a GitHub for Docker containers.<\/p>\n

But what if you want to host your own registry separated from the public one? Well, Docker Inc. has open sourced their Registry application on GitHub.<\/p>\n

This tutorial will take you though the process of setting up a private Docker registry using CoreOS on a new VPS.<\/p>\n

CoreOS + Docker<\/h3>\n

We won’t be spending a ton of time going over exactly what Docker and CoreOS can do, as it’s outside the scope of this tutorial. In essence, CoreOS is designed for massive server clusters, it’s small, fast and gets regular security updates automatically. Its root file system is also read-only, meaning you must use Docker to run any kind of software that is not included with the base install.<\/p>\n

This makes Core OS a perfect host system for Docker!<\/p>\n

Pulling and running the latest registry<\/h3>\n

Docker Inc. has provided the Registry as a top level image, this means that we can pull it down with a simple:<\/p>\n

docker pull registry\r\n<\/code><\/pre>\n

This can take a few minutes depending on the connection speed.<\/p><\/blockquote>\n

A plus of being a top level image also means it gets regular support and updates.<\/p>\n

Now let’s test out the registry. We can create a new container using the registry image:<\/p>\n

docker run -p 5000:5000 -d --name=basic_registry registry\r\n<\/code><\/pre>\n

For those who haven’t used Docker too much, the\u00a0-p<\/code>\u00a0flag stands for\u00a0PORT<\/code>, meaning we are exposing port 5000 on from the container onto host port 5000.<\/p>\n

The\u00a0-d<\/code>\u00a0flag stands for\u00a0daemon<\/code>, this will cause the container to run in the background and not print output to the current SSH session, we also want to name this basic test container using the\u00a0--name<\/code>\u00a0option so that we can easily manage it later.<\/p>\n

Make sure that your basic registry container is running using\u00a0docker ps<\/code>. The output should look similar to:<\/p>\n

CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                    NAMES\r\nedfb54e4a8c4        registry:0.8.1      \"\/bin\/sh -c 'exec do   7 seconds ago       Up 6 seconds        0.0.0.0:5000->5000\/tcp   basic_registry\r\n<\/code><\/pre>\n

Also, visit\u00a0http:\/\/YOUR_IP:5000<\/code>\u00a0in your web browser, and you should get a message like the following:<\/p>\n

\"docker-registry server (dev) (v0.8.1)\"\r\n<\/code><\/pre>\n

Notice the word\u00a0dev<\/code>\u00a0in the parenthesis. This means that the server is currently running the dev config. We’ll look over more configuration soon.<\/p><\/blockquote>\n

You now have your own (very basic) container registry running! But we’re not done yet.<\/p>\n

Maybe you want to keep this private from prying eyes, or maybe store your images on Amazon S3 instead of local storage. Let’s go over the various configuration options in the next section.<\/p>\n

Before we move on, let’s kill the test container so that we don’t run into conflicting ports.<\/p>\n

docker kill basic_registry\r\n<\/code><\/pre>\n

Registry configuration<\/h3>\n

There are two ways that we can pass configuration to the Docker Registry. One way is by passing environment variables to a new container, and the other is to add a configuration file.<\/p>\n

Here’s a few of the common configuration options we’ll be using:<\/p>\n

    \n
  • loglevel<\/code>\u00a0– The minimum amount of information to log to the console. Default is\u00a0info<\/code>.<\/li>\n
  • standalone<\/code>\u00a0– Should this Registry act on its own? (Never queries the public registry.) Default is\u00a0true<\/code>.<\/li>\n
  • index_endpoint<\/code>\u00a0– If not standalone, what other index will we query? Default\u00a0index.docker.io<\/code>.<\/li>\n
  • cache<\/code>\u00a0and\u00a0cache_lru<\/code>\u00a0– Options pertaining to using a Redis cache for small files, we’ll touch on this later.<\/li>\n
  • storage<\/code>\u00a0– What storage backend should we use for this server? (In this tutorial we’ll be using local).<\/li>\n
  • storage_path<\/code>\u00a0– If using local storage, what directory should we use to keep files in?<\/li>\n<\/ul>\n

    Before we get working with the configuration, we need a base file to work with. The file from the Docker Registry repository on GitHub will work just fine:<\/p>\n

    wget https:\/\/raw.githubusercontent.com\/docker\/docker-registry\/0.8\/config\/config_sample.yml\r\n<\/code><\/pre>\n

    The file should save successfully with an output such as:<\/p>\n

    2014-09-14 14:09:01 (156 MB\/s) - 'config_sample.yml' saved [5384\/5384]\r\n<\/code><\/pre>\n

    Great! Now we can modify this file to fit our needs.<\/p>\n

    The only text editor that comes with Core OS is\u00a0vim<\/code>, but don’t worry if you’ve never used it before, this will explain step by step what to edit and how to do it.<\/p>\n

    vim config_sample.yml\r\n<\/code><\/pre>\n

    Once you have the file open, hit the\u00a0I<\/code>\u00a0and the bottom right corner should display:\u00a0-- INSERT --<\/code>\u00a0for insert mode. Scroll all the way to the bottom of the file using your arrow keys, you should see a section labeled\u00a0prod<\/code>.<\/p>\n

    We’ll be changing the two lines, the changes are below<\/p>\n

    prod:\r\n    <<: *local\r\n    storage_path: _env:STORAGE_PATH:\/data\r\n<\/code><\/pre>\n

    What we’ve done is change the\u00a0prod<\/code>\u00a0configuration to derive from the\u00a0local<\/code>\u00a0section instead of the\u00a0s3<\/code>\u00a0section. Then we overwrote the\u00a0storage_path<\/code>\u00a0to use the path\u00a0\/data<\/code>\u00a0inside the new container.<\/p>\n

    Once you’ve confirmed that all the changes are correct, hit\u00a0ESC<\/code>\u00a0to exit insert mode and type\u00a0:wq<\/code>\u00a0(this means write the changes to the file, and quit vim.)<\/p>\n

    Now let’s rename the file to just\u00a0config.yml<\/code><\/p>\n

    mv config_sample.yml config.yml\r\n<\/code><\/pre>\n

    Redis caching (optional)<\/h3>\n

    If you’d like to use redis to speed up your container registry, it’s as simple as pulling a new container from the public registry and adding a few more lines of configuration.<\/p>\n

    First, pull the top level image of Redis:<\/p>\n

    docker pull redis\r\n<\/code><\/pre>\n

    Once the image is pulled successfully, we can run it and name it just like we did with the test registry:<\/p>\n

    docker run -d --name registry-redis redis\r\n<\/code><\/pre>\n

    Because redis is in memory, we don’t need to do any configuration for it, as we will link it to the registry container in later steps.<\/p>\n

    Once again, ensure it’s running by using\u00a0docker ps<\/code>:<\/p>\n

    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES\r\n54f65641eccf        redis:2.8           \"redis-server\"      2 seconds ago       Up 1 seconds        6379\/tcp            registry-redis\r\n<\/code><\/pre>\n

    Now re-open the\u00a0config.yml<\/code>\u00a0in\u00a0vim<\/code>\u00a0and enter insert mode just like the first time we edited it.<\/p>\n

    Add the following lines below the\u00a0prod<\/code>\u00a0section, being sure to indent properly. This time we’re only adding\u00a0cache<\/code>\u00a0and\u00a0cache_lru<\/code>.<\/p>\n

    cache:\r\n    host: _env:REDIS_PORT_6379_TCP_ADDR\r\n    port: _env:REDIS_PORT_6379_TCP_PORT\r\n    db: 0\r\n\r\ncache_lru:\r\n    host: _env:REDIS_PORT_6379_TCP_ADDR\r\n    port: _env:REDIS_PORT_6379_TCP_PORT\r\n    db: 1\r\n<\/code><\/pre>\n

    The environment variables\u00a0REDIS_PORT_6379_TCP_ADDR<\/code>\u00a0and\u00a0REDIS_PORT_6379_TCP_PORT<\/code>\u00a0are passed to the registry container upon linkage with the Redis container.<\/p>\n

    With that, you now have setup a Redis container that will work hand-in-hand with your registry container. Now onto building the registry!<\/p>\n

    Building the container<\/h3>\n

    We have all the configuration set and ready, now we need to build the actual registry container.<\/p>\n

    Fire up\u00a0vim Dockerfile<\/code>\u00a0to create a new Dockerfile. Enter insert mode and follow the edits below.<\/p>\n

    FROM registry:latest\r\n\r\n# Add the custom configuration file we made \r\nADD .\/config.yml \/docker-registry\/config\/config.yml\r\n\r\n# Create the data directory\r\nRUN mkdir \/data\r\n\r\n# Set the configuration file to config.yml\r\nenv DOCKER_REGISTRY_CONFIG \/docker-registry\/config\/config.yml\r\n\r\n# Make sure we use the prod configuration settings \r\nenv SETTINGS_FLAVOR prod\r\n<\/code><\/pre>\n

    What we’ve done above is essentially extend the registry image so it will use our configuration file and settings. A Dockerfile is a set of build instructions for Docker to read and build. If you’d like to learn more on Dockerfiles and their syntax, take a look at the official Docker site documentation.<\/p>\n

    Next we need to build the container for use.<\/p>\n

    docker build -t my_registry .\r\n\r\n\r\nSending build context to Docker daemon 13.82 kB\r\nSending build context to Docker daemon \r\nStep 0 : FROM registry\r\n ---> e42d15ec8417\r\nStep 1 : ADD .\/config.yml \/docker-registry\/config\/config.yml\r\n ---> 4339f026d459\r\nRemoving intermediate container 2d5138fbcd34\r\nStep 2 : RUN mkdir \/data\r\n ---> Running in a090f0bdbfd1\r\n ---> 8eb27ba6e12a\r\nRemoving intermediate container a090f0bdbfd1\r\nStep 3 : env DOCKER_REGISTRY_CONFIG \/docker-registry\/config\/config.yml\r\n ---> Running in 565b5bfb2b22\r\n ---> 914462e46dc0\r\nRemoving intermediate container 565b5bfb2b22\r\nStep 4 : env SETTINGS_FLAVOR prod\r\n ---> Running in 31a92847b851\r\n ---> b5949575c374\r\nRemoving intermediate container 31a92847b851\r\nSuccessfully built b5949575c374\r\n<\/code><\/pre>\n

    Now we are ready to run!<\/p>\n

    Let’s make a directory on our host system to mount in the container as the\u00a0\/data<\/code>\u00a0volume.<\/p>\n

    mkdir registry-data\r\n<\/code><\/pre>\n

    Now we can spin up a new container. If you plan on using the Redis cache, use the 2nd command below.<\/p>\n

    # For a non-Redis cache registry\r\ndocker run -d -p 5000:5000 -v \/home\/core\/registry-data:\/data --name=private_reg my_registry\r\n\r\n# For a Redis cached registry (Must have followed Redis Caching section above)\r\ndocker run -d -p 5000:5000 -v \/home\/core\/registry-data:\/data --name=private_reg --link registry-redis:redis my_registry\r\n<\/code><\/pre>\n

    To ensure that your server is running correctly, visit\u00a0http:\/\/YOUR_IP:5000<\/code>. You will see the following message:<\/p>\n

    \"docker-registry server (prod) (v0.8.1)\"\r\n<\/code><\/pre>\n

    Notice the\u00a0(prod)<\/code>\u00a0meaning our configuration changes were successful!<\/p>\n

    Configure your local Docker client<\/h3>\n

    Now that we have our own running registry, we want the Docker client on our local machines to start using it. Usually you would use the command:\u00a0docker login<\/code>, but for our use, we need to add one more argument to the login command:<\/p>\n

    docker login YOUR_IP:5000\r\n<\/code><\/pre>\n

    Enter a username and password (think of this like making a new account) and ignore the message that states you must activate it.<\/p>\n

    Next, let’s pull a stock image, and push it up to our own repository.<\/p>\n

    # Pull the busybox image from the public registry\r\ndocker pull busybox\r\n\r\n# Tag it with our IP\/URL\r\ndocker tag busybox YOUR_IP:5000\/busybox\r\n\r\n# Push it to our newly made registry\r\ndocker push YOUR_IP:5000\/busybox\r\n<\/code><\/pre>\n

    If everything pushes correctly the final message should be along the lines of:<\/p>\n

    Pushing tag for rev [a9eb17255234] on \r\n<\/code><\/pre>\n

    Congratulations! You have setup your very own docker repository.<\/p>\n

    What’s next?<\/h3>\n

    Here’s some ideas on how to improve your new private registry:<\/p>\n

      \n
    • Reverse proxy using Nginx or Apache to place additional security in front of it, like simple HTTP auth.<\/li>\n
    • Get a domain for your server and setup it up so you may access your registry with something like: registry.mysite.com<\/li>\n
    • Purchase (or self-sign) an SSL certificate to add even more protection if your containers contain sensitive information.<\/li>\n<\/ul>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","format":"standard","manualknowledgebasecat":[242,387,388],"manual_kb_tag":[389,390],"_links":{"self":[{"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/manual_kb\/2661"}],"collection":[{"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/manual_kb"}],"about":[{"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/types\/manual_kb"}],"author":[{"embeddable":true,"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/comments?post=2661"}],"version-history":[{"count":2,"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/manual_kb\/2661\/revisions"}],"predecessor-version":[{"id":2664,"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/manual_kb\/2661\/revisions\/2664"}],"wp:attachment":[{"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/media?parent=2661"}],"wp:term":[{"taxonomy":"manualknowledgebasecat","embeddable":true,"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/manualknowledgebasecat?post=2661"},{"taxonomy":"manual_kb_tag","embeddable":true,"href":"https:\/\/support.aklwebhost.com\/wp-json\/wp\/v2\/manual_kb_tag?post=2661"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}