Configure multi-store instances in Docker with Nginx
Learn how to configure Docker and Nginx to route multiple hostnames to separate application instances.
Lesson Content
Magento supports multiple websites and store views, but the web server must tell Magento which scope to load for each hostname. In this lesson, we configure a second website in Docker with Nginx.
Start in the Admin under Stores -> All Stores. Create a second website named Foo website, then create its store and store view. Keep the codes descriptive and consistent, such as foo_website, foo_website_store, and foo_website_store_view. This makes the scope clear whenever you reference a website, store, or store view.
Next, configure the base URLs for the new website under Stores -> Configuration -> Web. Switch the scope to Foo website, disable Use Default Value for both Base URLs and Base URLs (Secure), and set both values to https://foo.test/. Save the configuration.
Whether you configure the hostname at the website or store-view scope depends on how the storefronts differ. Separate websites are generally appropriate for completely different sites, while store views are commonly used for languages or storefronts that share the same website and store configuration.
To make the two storefronts easy to distinguish, open Content -> Design -> Configuration, select the Foo website scope, and upload a different logo. The storefronts can otherwise use the same default configuration.
Magento uses the MAGE_RUN_CODE and MAGE_RUN_TYPE environment variables to select the scope for an incoming request. MAGE_RUN_TYPE identifies the scope type, such as website, and MAGE_RUN_CODE identifies the website code.
The Nginx image supplied by docker-magento does not contain the custom mappings for your hostnames, so replace the existing Nginx image with a locally built image. In docker-compose.yml, change the Nginx service, named app, from using the image directly to building from images/nginx:
services:
app:
build: images/nginxKeep the other existing Nginx service configuration in place. The important change is replacing the image property with the build property and pointing it at the directory that contains your custom Dockerfile.
Create images/nginx/Dockerfile using the original Nginx image as its base. Use the same image value that the Nginx service previously referenced:
FROM markoshust/magento-nginx:1.13-8
COPY ./conf/default.conf /etc/nginx/conf.d/The base image is the image name and tag from your original docker-compose.yml file, markoshust/magento-nginx:1.13-8 in this example.
The original Nginx image includes a default.conf file. Copy that file into images/nginx/conf/default.conf, then add the host mapping near the top of the file and the runtime variables inside the SSL server block:
upstream fastcgi_backend {
server unix:/sock/docker.sock;
}
map $http_host $MAGE_RUN_CODE {
default base;
foo.test foo_website;
}
server {
listen 8000;
return 301 https://$host$request_uri;
}
server {
listen 8443 ssl;
ssl_certificate /etc/nginx/certs/nginx.crt;
ssl_certificate_key /etc/nginx/certs/nginx.key;
server_name magento234.test foo.test;
set $MAGE_ROOT /var/www/html;
set $MAGE_RUN_TYPE website;
include /var/www/html/nginx[.]conf;
}This is the complete file. The map sets the default website code to base and maps foo.test to foo_website. The server_name directive allows Nginx to serve both hostnames, while MAGE_RUN_TYPE tells Magento to load a website scope.
If you have more websites, add another entry to the map and another hostname to server_name:
map $http_host $MAGE_RUN_CODE {
default base;
foo.test foo_website;
bar.test bar_website;
}Nginx also needs to pass these variables to PHP. Create a project-level copy of the Magento nginx.conf.sample file named src/nginx.conf. Near the existing FastCGI parameter directives, add:
fastcgi_param MAGE_RUN_TYPE $MAGE_RUN_TYPE;
fastcgi_param MAGE_RUN_CODE $MAGE_RUN_CODE;Keep the rest of the copied nginx.conf file unchanged. MAGE_RUN_TYPE comes from the Nginx server configuration, and MAGE_RUN_CODE comes from the hostname map. Requests to magento234.test therefore use base, while requests to foo.test use foo_website.
Mount the new file into the containers. In docker-compose.dev.yml, the existing bind mount in the app service's volumes points to the sample file:
- ./src/nginx.conf.sample:/var/www/html/nginx.conf:delegatedRemove .sample from the source path:
- ./src/nginx.conf:/var/www/html/nginx.conf:delegatedThis ensures Docker mounts the customized nginx.conf file instead of the original sample.
Add the new hostname to your local hosts file so it resolves to Docker. Edit /etc/hosts with root privileges and add foo.test using the same address as magento234.test:
sudo vi /etc/hostsFor example, if the existing entry is:
127.0.0.1 ::1 magento234.testadd:
127.0.0.1 ::1 foo.testGenerate SSL certificates for both hostnames and restart the containers:
bin/setup-ssl magento234.test foo.testThis also detects the new Nginx build configuration and builds the custom image. If you later change default.conf or the Dockerfile, rebuild the image manually:
docker-compose buildLoad https://magento234.test to confirm that the original website still works. Then load https://foo.test. Magento now receives MAGE_RUN_TYPE=website and MAGE_RUN_CODE=foo_website, so it loads the Foo website configuration and displays its logo.
This same approach lets you customize other parts of the Nginx or PHP configuration. Create a project-level version of the configuration, copy it into the relevant image when necessary, and bind mount it into the container where Docker needs to use it.
Join the discussion!
Comments
Want to comment on this lesson?
Log in to leave comments.