How can we help you today?

Hypernode-docker

Created by: Rens Zuurbier

Modified on: Fri, 29 May, 2020 at 12:54 PM


The official Hypernode Docker image for Magento development is now available. This image can be used to set up a fast and easy local development environment for Hypernode, or as a build machine in a CI environment representative of the production environment. The image contains the exact same packages and configuration as a real Hypernode except for some Docker specific tweaks. By testing and developing against this image you can be sure that when you deploy to a Hypernode in production there will be no surprises because of different software versions or configurations.

Interested in a case study? Read this article about the Hypernode docker of one of our partners!

TABLE OF CONTENTS

About the Hypernode Docker Image

We build this image multiple times a day (every time we do a release) by applying our configuration management on the phusion/baseimage-docker 'fat' container. By treating the Docker as a lightweight VM instead of as a vehicle for a single process we stay close to what an actual Hypernode actually looks like. No micro-services or a multi-container application, but a single instance with minimal network overhead and all batteries included.

The hypernode-docker image has SSH, PHP, NGINX, MySQL, Redis and Varnish. The biggest difference between a real Hypernode and this container is that this environment does not have an init system. While it is possible to run systemd within a Docker Container if the host is also runs systemd, we choose not to do so to achieve greater compatibility and user-friendliness.

Usage

First of all download the latest version of Docker for Windows or Mac from the Docker website and make sure to install Docker on your computer. If you are working with Linux you can find all the info to install Docker in their documentation Docker Docs.

Start the Docker and logging in

Starting a container

docker pull docker.hypernode.com/byteinternet/hypernode-docker:latest
docker run -p 222:22 -p 8080:80 -p 8025:8025 docker.hypernode.com/byteinternet/hypernode-docker:latest

This makes the SSH, HTTP, and Mailhog ports available on the localhost. If you need any other ports (Such as 443 for HTTPS, or 2222 for sftp) available, you can insert these in the command above. In this example you should use the following command to connect to the container:

# Login as app user, obviously you can replace "app" with "root" to login as root
ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -p 222 app@127.0.0.1

The password is ‘insecure_docker_ssh_password’.

Checker whether or not you're are in the Docker environment

# This file does not exist on real Hypernodes
app@e4b7d958e69c:~$ ls /etc/hypernode/is_docker
/etc/hypernode/is_docker

No you're ready to use the hypernode-importer to import a shop from a remote server.

hypernode-importer --host yourhypernode.hypernode.io --path /data/web/public --set-default-url

To see the container in your browser you should change the base-url to “http://127.0.0.1:8080/” and don’t forget to flush your cache afterwards:

Magento 1
How to change base-urls in Magento 1

magerun ca:fl

Magento 2
How to change base-url in Magento 2

magerun ca:fl
cd magento2
magerun2 ca:fl

General Docker Commands

You might want to start several docker containers to develop multiple webshops. These commands may come in handy:

# Find the container ID
docker ps -a
CONTAINER ID        IMAGE                                                       COMMAND             CREATED             STATUS                    PORTS                                                                                                            NAMES
9187ce8348b0        docker.hypernode.com/byteinternet/hypernode-docker:latest   "/sbin/my_init"     12 days ago         Exited (255) 7 days ago   443/tcp, 1025/tcp, 3306/tcp, 6081/tcp, 8800/tcp, 8843/tcp, 8888/tcp, 0.0.0.0:222->22/tcp, 0.0.0.0:8080->80/tcp   nostalgic_swirles
 
# Find the IP address of the container
docker inspect -f '{{ .NetworkSettings.IPAddress }}' "9187ce8348b0"
172.17.0.2
 
# Run/Start container
docker start 9187ce8348b0
 
# Stop container
docker stop 9187ce8348b0
 
# Remove container (container must be stop before it could be removed)
docker rm 9187ce8348b0

Restarting services

Because systemctl is not available inside the container, the services are started by an init script on container startup. Note that because the systemd unit files are not parsed there could be a slight drift between what commandline flags the processes actually use in production compared to in this contanier.

To restart all services run:

bash /etc/my_init.d/60_restart_services.sh

If you only want to restart a specific service, inspect the restart_services.sh script and kill the screen for the service you want to restart. Then run the corresponding screen command to start the service again.

Starting the container

running the container on the foreground

To start the container in the foreground, run the following command:

$ docker pull docker.hypernode.com/byteinternet/hypernode-docker:latest
$ docker run -p 222:22 -p 8080:80 -p 8025:8025 docker.hypernode.com/byteinternet/hypernode-docker:latest
*** Running /etc/my_init.d/00_regen_ssh_host_keys.sh...
*** Running /etc/my_init.d/10_login_instructions.sh...
_
/\ /\_ _ _ __ ___ _ __ _ __ ___ __| | ___
/ /_/ / | | | '_ \ / _ \ '__| '_ \ / _ \ / _` |/ _ \
/ __ /| |_| | |_) | __/ | | | | | (_) | (_| | __/
\/ /_/ \__, | .__/ \___|_| |_| |_|\___/ \__,_|\___|
|___/|_|
 
Host/IP: xxxxx-dummytag-docker.nodes.hypernode.io (172.17.0.3)
Account_id: 666
Release: release-5278-28-ga9d3844 @ 2018-06-05 12:56:34 UTC
 
Handy commands (more at https://support.hypernode.com):
 
livefpm (see live PHP status)
tal | pnl (follow live requests)
 
hypernode-importer (import a Magento shop)
hypernode-image-optimizer (reduce image size)
hypernode-ftp (manage FTP accounts)
 
magerun list (many useful extensions)
 
------------------------------------------------------------------------------
The SSH daemon will be up in a couple of seconds, you can login with: ssh -A app@172.17.0.3
*** Running /etc/my_init.d/50_copy_key.sh...
*** Running /etc/my_init.d/50_fix_mailname.sh...
*** Running /etc/my_init.d/51_postfix.sh...
* Starting Postfix Mail Transport Agent postfix
...done.
*** Running /etc/my_init.d/60_restart_services.sh...
Killing old Hypernode services
Killing any old NGINX service
Killing any old Redis service
Killing any old PHP-FPM service
Killing any old MySQL service
Killing any old Mailhog service
Killing any old Varnish service
Giving any old services 5 seconds to stop..
No Sockets found in /var/run/screen/S-root.
 
Starting new detached hypernode services. See screen -x
Starting NGINX
Starting Redis
Starting PHP
Starting MySQL
Starting Mailhog
Starting Varnish
Giving the new services a couple of seconds to start..
hypernode-docker status: everything ok
*** Running /etc/rc.local...
*** Booting runit daemon...
*** Runit started as PID 312


You can now log in with SSH using the IP address seen in the output.

Running The Container on The Background

To start the container in the background, run the following command:

$ docker run -d -p 222:22 -p 8080:80 -p 8025:8025 docker.hypernode.com/byteinternet/hypernode-docker:latest
36532b58822cf27f74234f6afc01db21fca15b480bf43634ae725db35047dc5a

The IP address of the container can then be found with:

$ docker inspect -f '{{ .NetworkSettings.IPAddress }}' 36532b58822cf27f74234f6afc01db21fca15b480bf43634ae725db35047dc5a
172.17.0.3

You can view the logs with docker logs

$ docker logs 36532b58822cf27f74234f6afc01db21fca15b480bf43634ae725db35047dc5a
*** Running /etc/my_init.d/00_regen_ssh_host_keys.sh...
*** Running /etc/my_init.d/10_login_instructions.sh...
_
/\ /\_ _ _ __ ___ _ __ _ __ ___ __| | ___
/ /_/ / | | | '_ \ / _ \ '__| '_ \ / _ \ / _` |/ _ \
/ __ /| |_| | |_) | __/ | | | | | (_) | (_| | __/
\/ /_/ \__, | .__/ \___|_| |_| |_|\___/ \__,_|\___|
|___/|_|
 
Host/IP: xxxxx-dummytag-docker.nodes.hypernode.io (172.17.0.3)
Account_id: 666
Release: release-5278-28-ga9d3844 @ 2018-06-05 12:56:34 UTC
 
Handy commands (more at https://support.hypernode.com):
 
livefpm (see live PHP status)
tal | pnl (follow live requests)
 
hypernode-importer (import a Magento shop)
hypernode-image-optimizer (reduce image size)
hypernode-ftp (manage FTP accounts)
 
magerun list (many useful extensions)
 
------------------------------------------------------------------------------
The SSH daemon will be up in a couple of seconds, you can login with: ssh -A app@172.17.0.3
*** Running /etc/my_init.d/50_copy_key.sh...
*** Running /etc/my_init.d/50_fix_mailname.sh...
*** Running /etc/my_init.d/51_postfix.sh...
* Starting Postfix Mail Transport Agent postfix
...done.
*** Running /etc/my_init.d/60_restart_services.sh...
Killing old Hypernode services
Killing any old NGINX service
Killing any old Redis service
Killing any old PHP-FPM service
Killing any old MySQL service
Killing any old Mailhog service
Killing any old Varnish service
Giving any old services 5 seconds to stop..
No Sockets found in /var/run/screen/S-root.
 
Starting new detached hypernode services. See screen -x
Starting NGINX
Starting Redis
Starting PHP
Starting MySQL
Starting Mailhog
Starting Varnish
Giving the new services a couple of seconds to start..
hypernode-docker status: everything ok
*** Running /etc/rc.local...
*** Booting runit daemon...
*** Runit started as PID 312

Importing a Magento shop

1. Add a hosts entry for the Docker

grep -q hypernode.hypernode.local /etc/hosts || echo "172.17.0.2 hypernode.hypernode.local" >> /etc/hosts

2. Start an SSH agent and add your key

eval $(ssh-agent -s)
ssh-add # Add your keys

3. Log in to the hypernode-docker container

# Log in with SSH agent forwarding
# The default password is 'insecure_docker_ssh_password', or use the insecure key
ssh -A root@172.17.0.2

4. Double-check you are in the Docker environment and not the real Hypernode

# This file does not exist on real Hypernodes
app@e4b7d958e69c:~$ ls /etc/hypernode/is_docker
/etc/hypernode/is_docker

5.

Run the hypernode-importer to import a shop from a real Hypernode

hypernode-importer --host yourhypernode.hypernode.io --path /data/web/public --set-default-url

6. Point your browser to the importer shop

Go to http://hypernode.hypernode.local/

Switching PHP versions

Unlike the hypernode-vagrant you can not just run hypernode-switch-php to change the PHP version. Because there is no systemctl to manage the services other steps must be performed. To switch to a different PHP version run the following commands:

# Edit /etc/my_init.d/60_restart_services.sh to use the correct PHP
vim /etc/my_init.d/60_restart_services.sh
# Change the enabled PHP
update-alternatives --set php $(which php7.1)
# Restart (all) services
bash /etc/my_init.d/60_restart_services.sh

Adding keys to Container

To create a Docker instance of hypernode-docker with your own keys, create a directory with your public key in it and a Dockerfile.

$ ls
key.pub Dockerfile
$ cat Dockerfile
FROM docker.hypernode.com/byteinternet/hypernode-docker:latest
MAINTAINER yourname 
 
ADD key.pub /tmp/key.pub
RUN cat /tmp/key.pub > /root/.ssh/authorized_keys && cat /tmp/key.pub > /data/web/.ssh/authorized_keys && rm -f /tmp/deployment.pub

Then build the Docker with:

docker build -t hypernode-with-keys .

And once finished, start the Docker with:

docker run hypernode-with-keys

Note: remember that you will also need to change the default app and root user passwords if you're looking to create a secure environment.

Inspecting Emails Sent from The Docker

Like in the hypernode-vagrant project, all emails are caught and redirected to a MailHog instance. You can visit the mailhog web interface on port 8025. So for example, if the IP of your container is 172.17.0.2 you would be able to access MailHog on http://172.17.0.2:8025/.

Alternatively you could set up a hosts entry like so on the host (not in the Docker):

grep -q hypernode.hypernode.local /etc/hosts || echo "172.17.0.2 hypernode.hypernode.local" >> /etc/hosts

And then visit the MailHog instance on http://hypernode.hypernode.local:8025.

Installing Magento 1

Make sure you have a hosts entry set up:

# Note that you need root to write to /etc/hosts
grep -q hypernode.hypernode.local /etc/hosts || echo "172.17.0.2 hypernode.hypernode.local" >> /etc/hosts

Switch to a Magento 1 compatible PHP version

# Log in as root
$ ssh root@172.17.0.2 -i keys/insecure_key
# Change the PHP service version to 7.0
sed -i 's/7\.1/7.0/g' /etc/my_init.d/60_restart_services.sh
# Update PHP symlinks
update-alternatives --set php $(which php7.0)
# Restart services
bash /etc/my_init.d/60_restart_services.sh
# Log out of the Docker
exit

Log in to the container as the app user:

ssh app@172.17.0.2 -i keys/insecure_key

Remove any Magento 2 specific NGINX configuration:

rm -rf /data/web/nginx/magento2.flag

Create a new database:

echo 'create database magento;' | mysql

Install Magento with n98-magerun:

# Write the n98-magerun config file:
cat << EOF > /data/web/.n98-magerun.yaml
commands:
N98\Magento\Command\Installer\InstallCommand:
installation:
defaults:
currency: EUR
locale: nl_NL
timezone: UTC
use_secure: no
use_rewrites: yes
session_save: files
admin_username: admin
admin_firstname: Firstname
admin_lastname: Lastname
admin_password: thisisanexamplePassword123456
admin_frontname: example
admin_email: example@example.com
encryption_key:
installation_folder: /data/web/public
 
magento-packages:
- name: byte-mag-mirror-latest
version: 1.9
dist:
url: http://magento.mirror.hypernode.com/releases/magento-latest.tar.gz
type: tar
extra:
sample-data: sample-data-1.9.1.0
EOF
 
# Install Magento 1
php -d memory_limit=1024M /usr/local/bin/n98-magerun install --magentoVersionByName=byte-mag-mirror-latest --dbHost=127.0.0.1 --dbUser=app --dbPass=$(cat /data/web/.my.cnf | grep pass | awk '{print$3}') --dbName=magento --installSampleData=no --useDefaultConfigParams=yes --installationFolder=/data/web/public --baseUrl=http://hypernode.hypernode.local --replaceHtaccessFile=no --no-interaction

Varnish on Docker

By default Varnish is already enabled, but won’t work because the server is missing some configuration in order to work correctly. This isn’t implemented because there were earlier issues with Varnish on a Vagrant environment.

If you want to experiment with Varnish in your Docker environment you should overwrite the content of “/etc/nginx/outside.conf”, to do this you need to log in as root user.

# Log in as the root user
ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -p 222 root@127.0.0.1

Overwrite the content of “/etc/nginx/outside.conf” to the following:

## Ansible managed: /srv/jenkins/workspace/hypernode-control-BUILD_CUSTOMER_DOCKER/playbooks/roles/magweb/templates/nginx/outside.conf modified on 2018-10-25 12:36:38 by jenkins on hn-integrate11
## This file defines the vhosts that are facing outward (port 80 / 443 for public, 8880 and 8888 / 8443 for staging).
# This is the auto server definition for docroot public
server {
# Log nullbytes in checkout pages post bodies
access_by_lua_file "/etc/nginx/request_security.lua";
 
## default vhost definition
# we need to define multiple ports because there is no overlap between what is allowed by some external services (cloudflare and adyen)
listen 80 default_server;
 
# Outside.conf will pass remote_addr to fastcgi as remote_addr, but inside.conf must
# pass http_x_real_ip. In order to still share the fastcgi_params file inside an include
# inside an include, we set this variable to remote_addr and set it to something else in inside.conf.
root /data/web/public;
## i'm redirecting to varnish here!
location / {
set $log_handler varnish;
proxy_pass http://127.0.0.1:6081;
proxy_read_timeout 900s; # equal to fastcgi_read_timeout at handlers.conf:16
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Host $http_host;
}
include /etc/nginx/security.conf;
# phpmyadmin should never pass through Varnish, so include an alias and a handler here
include /etc/nginx/phpmyadmin.conf;
include /etc/nginx/app/public.*;
include /etc/nginx/app/server.*;
# in case the user wants to route a part of the site directly to FPM in override files
include /etc/nginx/handlers.conf;
# blocking bots tool
include /etc/nginx/server.blocked_bots.conf;
}
# This is the auto server definition for docroot staging
server {
# Log nullbytes in checkout pages post bodies
access_by_lua_file "/etc/nginx/request_security.lua";
 
## default vhost definition
# we need to define multiple ports because there is no overlap between what is allowed by some external services (cloudflare and adyen)
listen 8880 default_server;
listen 8888;
 
# Outside.conf will pass remote_addr to fastcgi as remote_addr, but inside.conf must
# pass http_x_real_ip. In order to still share the fastcgi_params file inside an include
# inside an include, we set this variable to remote_addr and set it to something else in inside.conf.
root /data/web/staging;
# Set a default document root, and store it in a variable. This variable will be used in the
# named location '@fastcgi_backend' to set the documentroot from which PHP-files will be served.
# This is needed to be able to change the documentroot for phpmyadmin later on.
include /etc/nginx/security.conf;
include /etc/nginx/magento.conf;
include /etc/nginx/phpmyadmin.conf;
include /etc/nginx/app/server.*;
# Cannot use an Nginx var in include statements. -WdG
# This line will include staging.* and public.* files if they exist.
include /etc/nginx/app/staging.*;
 
# blocking bots tool
include /etc/nginx/server.blocked_bots.conf;
}

Restart Services


Restart the services after you changed the config file.

bash /etc/my_init.d/60_restart_services.sh

That’s it, Varnish should be working fine now! You can see the results when you enter ‘varnishhist’ in the CLI and click around in your webshop at http://127.0.0.1:8080/

R
Rens is the author of this solution article.

Did you find it helpful? Yes No

Send feedback
Sorry we couldn't be helpful. Help us improve this article with your feedback.