I want to build anycable with my application but I get this error:
ActionController::RoutingError (No route matches [GET] "/cable")
and this is error in the browser:
action_cable.js:241 WebSocket connection to 'wss://portal.comp-moto.com/cable' failed:
This is my docker-compose.yml
version: "3"
volumes:
data-uploads:
packs:
services:
app:
build:
context: .
dockerfile: ./dockers/app/Dockerfile
container_name: comp_moto_app
restart: unless-stopped
ports:
- 3000:3000
volumes:
- .:/app
- /app/node_modules
- /app/public/assets
- /app/public/packs
depends_on:
- redis
environment:
- REDIS_URL_CACHING=redis://redis@redis:6379/0
db:
image: "postgres:14.1-alpine"
container_name: comp_moto_db
environment:
POSTGRES_USER: ${DOCKER_DB_USER}
POSTGRES_PASSWORD: ${DOCKER_DB_PASSWORD}
POSTGRES_DB: ${DOCKER_DB_NAME}
volumes:
- /docker_data/comp_moto_app/postgres:/var/lib/postgresql/data
ports:
- 5432:5432
nginx:
build:
context: .
dockerfile: ./dockers/web/Dockerfile
container_name: comp_moto_web
restart: unless-stopped
ports:
- 80:80
- 443:443
depends_on:
- app
volumes:
- ./dockers/web/nginx.conf:/etc/nginx/conf.d/default.conf
- ./public:/app/public
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
certbot:
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
redis:
image: redis:6.2.6-alpine
container_name: comp_moto_redis
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- /docker_data/comp_moto/production/redis:/data
- ./dockers/redis/redis.conf:/usr/local/etc/redis/redis.conf
ports:
- 6379:6379
delayed_job:
build:
context: .
dockerfile: ./dockers/delayed_job/Dockerfile
container_name: comp_moto_delayed_job
command: bundle exec rails jobs:work
depends_on:
- db
volumes:
- .:/app
anycable:
build:
context: .
dockerfile: ./dockers/cable/Dockerfile
container_name: comp_moto_anycable
command: bundle exec anycable
environment:
ANYCABLE_REDIS_URL: redis://redis@redis:6379/0
ANYCABLE_RPC_HOST: 0.0.0.0:50051
ANYCABLE_DEBUG: 1
ports:
- '50051'
depends_on:
- redis
- db
ws:
image: anycable/anycable-go:latest-alpine
container_name: comp_moto_ws
ports:
- '8080:8080'
environment:
ANYCABLE_HOST: "0.0.0.0"
ANYCABLE_REDIS_URL: redis://redis@redis:6379/0
ANYCABLE_RPC_HOST: anycable:50051
ANYCABLE_DEBUG: 1
depends_on:
- redis
- anycable
sidekiq:
build:
context: .
dockerfile: ./dockers/sidekiq/Dockerfile
container_name: comp_moto_sidekiq
command: bundle exec sidekiq
depends_on:
- db
- redis
volumes:
- data-uploads:/app/public/uploads
this is my Dockerfile for anycale service
FROM ruby:3.0.1-alpine
RUN apk add --no-cache --update build-base \
linux-headers \
postgresql-dev \
tzdata \
git \
nodejs \
yarn \
libc6-compat
COPY Gemfile Gemfile.lock package*.json yarn.lock ./
RUN gem install bundler && bundle install --jobs 3
COPY . ./
EXPOSE 50051
ENTRYPOINT ["bundle", "exec"]
CMD ["anycable"]
I also add these to production.rb
config.after_initialize do
config.action_cable.url = ActionCable.server.config.url = ENV.fetch("CABLE_URL", "wss://portal.comp-moto.com/cable") if AnyCable::Rails.enabled?
end
config.action_cable.url = 'wss://portal.comp-moto.com/cable'
config.action_cable.allowed_request_origins = [ 'https://portal.comp-moto.com', /https:\/\/portal.comp-moto.com.*/ ]
this is anycale.yml
development:
redis_url: redis://localhost:6379/1
production:
redis_url: redis://:redis@redis:6379/0
access_logs_disabled: false
I use nginx, here is nginx
upstream rails_app {
server app:3000;
}
server {
# define your domain
listen 80;
server_name portal.comp-moto.com;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
server {
listen 443 ssl;
server_name portal.comp-moto.com;
server_tokens off;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
proxy_send_timeout 1800;
client_max_body_size 20M;
client_body_buffer_size 20M;
client_body_timeout 1800;
client_header_timeout 1800;
keepalive_timeout 1800;
send_timeout 1800;
# define the public application root
root /app/public;
index index.html;
# serve static (compiled) assets directly if they exist (for rails production)
location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/ {
try_files $uri @rails;
access_log off;
gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
# send non-static file requests to the app server
location / {
try_files $uri @rails;
}
ssl_certificate /etc/letsencrypt/live/portal.comp-moto.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/portal.comp-moto.com/privkey.pem;
location @rails {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Host $host;
proxy_redirect off;
proxy_pass http://rails_app;
}
location /wss {
proxy_pass https://portal.comp-moto.com:8080;
include proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}