Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Write a chat room application chitchat on Docker Swarm

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "writing a chat room application chitchat on Docker Swarm". In the daily operation, I believe that many people have doubts about writing a chat room application chitchat on Docker Swarm. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts of "writing a chat room application chitchat on Docker Swarm". Next, please follow the editor to study!

The biggest difference between Phoenix web applications and web applications implemented in other languages / frameworks is that Phoenix applications can maintain a good ability to scale out even when they are stateful, thanks to its underlying Erlang OTP support. In order to share the state among the nodes in the cluster, each node only needs to know each other and does not need to open a separate state container (such as Redis), which makes the architecture of Phoenix applications more simple and clear. Elixir 1.9 also adds support for release, which makes it easier to package and deploy. However, these are limited to the traditional, pre-known cluster capacity and how each node IP is deployed. How to deploy Phoenix applications on Docker Swarm without knowing the IP of each node in advance and achieve dynamic expansion has become the next challenge. Today, try to deploy the most typical stateful web application-a WebSocket-based chat room.

Write a chat room application chitchat

I won't write because it's not the point. If you can't write, just go to GitHub and pull the code.

Release preparation

Only the simplest preparations are made here.

$mix release.init

We also need to add a line of code to the config/prod.secret.exs to let our release artifact know that we want to start all relevant application.

Config: chitchat, ChitchatWeb.Endpoint, server: true create Docker image

Create a Dockerfile in the root directory of the project and add the following:

FROM elixir:1.9.1-alpine as build# install build dependenciesRUN apk add-- update git build-base nodejs npm yarn python# prepare build dirRUN mkdir / appWORKDIR / app# install hex + rebarRUN mix local.hex-- force & &\ mix local.rebar-- force# set build ENVENV MIX_ENV=prod# install mix dependenciesCOPY mix.exs mix.lock. / COPY config configRUN mix deps.getRUN mix deps.compile# build assetsCOPY assets assetsRUN cd assets & & npm install & & npm run deployRUN mix phx.digest# build projectCOPY priv privCOPY lib libRUN Mix compile# build releaseCOPY rel relRUN mix release# prepare release imageFROM alpine:3.9 AS appRUN apk add-- update bash opensslRUN mkdir / appWORKDIR / appCOPY-- from=build / app/_build/prod/rel/chitchat. / RUN chown-R nobody: / appUSER nobodyENV HOME=/app

This is copied directly from the official Phoenix documentation, with nothing but a change in the application name and the addition of npm to apk add and the release of COPY rel rel.

This is a Dockerfile of multi-stage. In order to make the final image as small as possible, we leave all the things that are not needed by Elixir, Mix, node.js and other runtimes in the image of the build phase, and only the things that come out of the final release (including the Erlang runtime) are put into the final image. The docker image I built here is about 35MB. Although I can build it now, I won't build it for the time being.

Create Swarm

For convenience, I only made a single-node swarm:

$docker swarm init

If you have more than 3 computers, you can also do full-size swarm. That's not the point, so skip it. If you don't know what to do, refer to the official tutorial.

Localize Docker Registry

Since the services deployed to the swarm cluster must use pre-built images (if each node builds its own image slowly and consumes resources), and in the actual production environment, each image may be very large (upper G), so we need a Docker Registry in the private network to register and share the image on each node.

Run on any manager node

$docker service create-- name registry-p 5000UR 5000 registry:2

This sentence will create a service called registry in your swarm, using the image of Docker's official registry:2, which exposes port 5000. It has only one replica.

Build an image and push it to Registry

Run command

$docker build-tag 127.0.0.1:5000/chitchat:0.1.0.

You can build a mirror image. The version number had better be the same as that in mix.exs. Note that Docker Registry doesn't seem to overwrite existing images (to be verified), so it's best not to use latest for version numbers. 127.0.0.1 registry 5000 is the IP address and port number of your swarm, which can be changed according to your actual situation. Run the command after building

$docker push 127.0.0.1:5000/chitchat:0.1.0

You can push the image to the local registry.

Docker-compose.yml

Create a docker-compose.yml in the root directory of the project and add the following:

Version: '3.7'services: app: image: 127.0.0.1:5000/chitchat:0.1.0 ports:-80 image 4000 entrypoint:. / bin/chitchat start deploy: mode: replicated replicas: 3

Apart from the deploy entry, this is the simplest docker-compose configuration file. Let's run first.

$docker-compose up

It should be able to run directly (although there will be warnings that the deploy entry is invalid), and it should be no problem accessing port 80 and connecting to ws.

Then we try to deploy to swarm (students on a single node remember to turn off the test run):

$docker stack deploy-c. / docker-compose.yml chitchat

Confirmation services are all up.

$docker stack services chitchat

You should see the following:

ID NAME MODE REPLICAS IMAGE PORTSx2eym27lc2b8 chitchat_app replicated 3 127.0.0.1:5000/chitchat:0.1.0 3 127.0.0.1:5000/chitchat:0.1.0 *: 80-> 4000/tcp

If you see that the REPLICAS is 3amp 3, the deployment is successful, and if it has been 0ax 3 all the time, check your code for problems.

For the next debugging, track the log first:

$docker service logs-f chitchat_app

Then open two browser windows / tabs, visit http://127.0.0.1/rooms/1, check the log to make sure ws is connected to a different replica, and if connected to the same one, refresh one of the windows until it is connected to a different replica. Try sending a message and you will find that you can't get it in another window!

What's the problem? The problem is that the epmd (Erlang Process Manager) on each node goes its own way and is not connected together. So the next step is to find a way to connect them.

We know that Elixir has a function Node.connect/1 that can connect to other nodes, as long as they have the same cookie. The problem is that this connection requires knowing the other person's IP or domain name or hostname in advance. However, in a container orchestration system (container orchestration system), the container's IP, domain name, and hostname are all assigned dynamically, especially after the container is down and restarted, its IP, domain name, and hostname are likely to change. In such a dynamic cluster, how can the container find its own brother?

The idea is to make use of Docker's DNS-based service discovery mechanism. In Docker Swarm, each service comes with a domain name for service discovery, which is tasks.,. In our configuration, it is tasks.chitchat_app. If you run nslookup tasks.chitchat_app in any replica container, you will see the IP addresses of all replica. With the IP address, all you have to do is know the basic name of the node (the node name @ preceding). This name is easy to find because the environment variable $RELEASE_NAME is already set when Elixir's release starts.

It looks good. Try it first. Let's go to Container 1 first (change that xxx to the actual value, but all you have to do is tap Tab):

$docker exec-it chitchat_app.1.xxx sh

Get the IP addresses of other containers:

$nslookup tasks.chitchat_app

Then attach to the running chitchat process and try to connect to another node (assuming its IP is 10.0.0.3):

$. / bin/chitchat remoteiex > Node.connect (: "chitchat@10.0.0.3")

You'll find that you can't connect. What's the problem? Look at the name of the current node:

Iex > Node.self (): "nonode@nohost"

That's the problem. Our node has no name! In order for each node to have its own name, we need to modify rel/env.sh.eex.

Modify rel/env.sh.eex

Release the following two lines:

Export RELEASE_DISTRIBUTION=nameexport RELEASE_NODE= "@ 127.0.0.1"

This file is used to generate env.sh, and env.sh is run each time the application is started to set environment variables.

One more question: how to replace 127.0.0.1 with the IP of the real container? If you run hostname-I in a container, you will get the current IP (interestingly, if you run this command on your own PC, you will only get 127.0.1.1). So we just have to change the RELEASE_NODE line to

Export RELEASE_NODE= "@ $(hostname-I)"

It's all OK. By the way, rel/env.bat.eex can not be changed, because our container does not run Windows but Alpine Linux.

Redeploy, try to connect to other nodes, and you can see that you can connect this time.

The next problem is how to make it connect automatically and periodically. Here I use a third-party library, Peerage.

Integrated Peerage

Please see the official website for the installation method. I only post my configuration:

# config/prod.exsconfig: peerage, via: Peerage.Via.Dns, dns_name: "tasks.chitchat_app", app_name: {: system, "RELEASE_NAME"}

The dns_name here is the DNS domain name that Peerage visits. App_name is the first part of the node name @. {: system, "RELEASE_NAME"} tells Peerage that the name should be found in the environment variable $RELEASE_NAME. Peerage periodically visits DNS to get IP, prefix @ to each IP, and then try to connect to these nodes.

Redeploy and run on some replica

. / bin/chitchat rpc "IO.inspect Node.list"

You will see the names of other nodes, which indicates that all nodes are connected.

You can also try to expand / shrink the current service (see docker service scale), kill a container (docker kill), and see if it behaves as expected.

At this point, the study of "writing a chat room application chitchat on Docker Swarm" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report